nvim/plugin/statusline.lua
2024-05-24 16:04:23 +01:00

186 lines
7.2 KiB
Lua

local statusline = {}
local theme = {
light_green = { fg = '#262626', bg = '#59946f' },
light_blue = { fg = '#262626', bg = '#5c91bf' },
light_orange = { fg = '#262626', bg = '#b6927b' },
light_red = { fg = '#262626', bg = '#e46876' },
light_grey = { fg = '#262626', bg = '#808080' },
light_violet = { fg = '#262626', bg = '#957fb8' },
dark_white = { fg = '#ffffff', bg = '#121212' },
dark_yellow = { fg = '#c4b28a', bg = '#121212' },
dark_grey = { fg = '#808080', bg = '#121212' },
}
local modes = {}
modes[110] = { name = 'Normal', color = 'light_green' }
modes[105] = { name = 'Insert', color = 'light_blue' }
modes[99] = { name = 'Command', color = 'light_green' }
modes[118] = { name = 'Visual', color = 'light_violet' }
modes[86] = { name = 'V-Line', color = 'light_violet' }
modes[22] = { name = 'V-Block', color = 'light_violet' }
modes[82] = { name = 'Replace', color = 'light_red' }
modes[115] = { name = 'Select', color = 'light_orange' }
modes[83] = { name = 'S-Line', color = 'light_orange' }
modes[19] = { name = 'S-Block', color = 'light_orange' }
modes[116] = { name = 'Terminal', color = 'light_blue' }
modes[33] = { name = 'Shell', color = 'light_grey' }
local function highlight(group, color, attrs)
local args = { group, 'guifg=' .. color.fg, 'guibg=' .. color.bg }
if attrs then
table.insert(args, 'gui=' .. attrs)
end
vim.cmd.highlight(args)
end
-- StatusLineLight is shows the mode and cursor information, it is dynamically
-- changed by statusline#mode(), give it a default.
highlight('StatusLineLight', theme.light_grey)
-- StatusLineDusk is shows additional information which is not always present,
-- give it a muted color.
highlight('StatusLineDusk', theme.light_grey, 'bold')
-- StatusLineDark shows the filename and filetype and takes up most of the
-- statusline, give it a dark background.
highlight('StatusLineDark', theme.dark_white)
-- StatusLineChange shows changes in the file by changing the colour of the
-- filename, give if a dark background.
highlight('StatusLineChange', theme.dark_yellow)
-- StatusLineFade shows the status of completion engines but using colors which
-- fade into the background to avoid grabbing attention.
highlight('StatusLineDuskFade', theme.dark_grey)
-- Get statusline mode and update StatusLineLight.
local function get_mode()
-- Map modes to a human readable name and a color.
local current_mode = modes[vim.fn.char2nr(vim.fn.mode())]
-- Update the StatusLineLight color.
highlight('StatusLineLight', theme[current_mode.color], 'bold')
return current_mode.name
end
-- Display cusor line/total and column
local position = '# ☰ %l/%L 󰠷 %2c '
-- Construct a statusline for special buffer types.
local function special(group, name, title)
-- Display current mode with dynamic highlights.
local line = '%#' .. group .. '# ' .. name .. ' '
-- Display filename with dark highlights.
line = line .. '%#StatusLineDark# ' .. title
-- Display current/total lines and column with dynamic highlights.
line = line .. '%=' .. '%#' .. group .. position
-- Combine the elements into a single string to be evaluated.
return line
end
-- Construct a statusline for generic buffer types.
local function generic(group, name)
-- Display current mode with dynamic highlights.
local line = '%#' .. group .. '# ' .. name .. ' '
-- Display spell or paste if set with dusk highlights in a group to swallow
-- the spaces when empty.
line = line .. '%#StatusLineDusk#%( ' .. '%{&spell ? "Spell " : ""}' ..
'%{&paste ? "Paste " : ""}' .. '%)'
-- Display filename with dark or changed highlights.
if vim.o.modified then
line = line .. '%#StatusLineChange#'
else
line = line .. '%#StatusLineDark#'
end
line = line .. ' %<%f'
-- Display readonly and nomodifiable if set.
line = line
.. '%#StatusLineDark#'
.. '%{&readonly ? " 🔒" : ""}'
.. '%{&modifiable ? "" : " ⛔"}'
-- Display filetype if set.
line = line .. '%=' .. '%#StatusLineDark# %{&filetype} '
-- Display fileencoding if not utf-8 and fileformat if not unix with dusk
-- highlights in a group to swallow spaces when empty.
line = line .. '%#StatusLineDusk#%( ' ..
'%{&fileencoding ==# "utf-8" ? "" : &fileencoding}' ..
'%{&fileformat ==# "unix" ? "" : "[".&fileformat."]"}' .. ' %)'
-- Display current/total lines and column with dynamic highlights.
line = line .. '%#' .. group .. position
-- Combine the elements into a single string to be evaluated.
return line
end
-- Define active statusline, this statusline is dynamic with StatusLineLight
-- being updated based on the current mode and only used for current buffer.
function _G.statusline_active()
local mode = get_mode()
if vim.o.buftype == 'help' then
if mode == 'Normal' then mode = 'Help' end
return special('StatusLineDusk', 'Help', '%F')
elseif vim.o.buftype == 'quickfix' then
-- Quickfix list and location list have the same buftype, the window has a
-- loclist flag, query the window info.
local info = vim.fn.getwininfo(vim.fn.win_getid())[1]
if mode == 'Normal' then
if info.loclist == 1 then
mode = 'Location'
else
mode = 'Quickfix'
end
end
local title = info.variables.quickfix_title
return special('StatusLineLight', mode, title)
elseif vim.o.buftype == 'terminal' then
return special('StatusLineLight', 'Terminal', '%f')
elseif vim.o.previewwindow then
if mode == 'Normal' then mode = 'Preview' end
return generic('StatusLineLight', mode)
elseif vim.o.filetype == 'man' then
return special('StatusLineDusk', 'Manual', '%f')
end
return generic('StatusLineLight', mode)
end
function _G.statusline_inactive()
local mode = modes[vim.fn.char2nr(vim.fn.mode())].name
local line = ''
if vim.o.buftype == 'help' then
line = special('StatusLineDusk', 'Help', '%F')
elseif vim.o.buftype == 'quickfix' then
-- Quickfix list and location list have the same buftype, the window has a
-- loclist flag, query the window info.
local info = vim.fn.getwininfo(vim.fn.win_getid())[1]
if info['loclist'] then mode = 'Location' else mode = 'Quickfix' end
line = special('StatusLineDusk', mode, info.variables.quickfix_title)
elseif vim.o.buftype == 'terminal' then
line = special('StatusLineDusk', 'Terminal', '%f')
elseif vim.o.previewwindow then
line = generic('StatusLineDusk', 'Preview')
elseif vim.o.filetype == 'man' then
line = special('StatusLineDusk', 'Manual', '%f')
else
line = generic('StatusLineDusk', 'Idle')
end
return line
end
-- Setup autocmds to set the statusline per buffer.
local group = vim.api.nvim_create_augroup('statusline', { clear = true })
-- Dynamically update the current buffer mode and color changes using %! to
-- call a function which is always evaluated on statusline update.
vim.api.nvim_create_autocmd({ 'BufEnter', 'WinEnter', 'BufWinEnter' }, {
pattern = '*',
group = group,
callback = function()
vim.cmd.setlocal("statusline=%{%v:lua.statusline_active()%}")
end
})
-- Statically set the statusline when leaving the buffer.
vim.api.nvim_create_autocmd({ 'BufLeave', 'WinLeave' }, {
pattern = '*',
group = group,
callback = function()
vim.cmd.setlocal("statusline=%{%v:lua.statusline_inactive()%}")
end
})
return statusline