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