local fn = vim.fn local api = vim.api local status_line_max_length = 5 -- TODO: only update this portion when needed instead of every render? local status_line_buffer_by_num = function(bufnum) local bufinfo = fn.getbufinfo(bufnum) local prefix = ' %#InactiveBuffer#' local suffix = '%* ' if bufinfo.changed then prefix = '%#DirtyBuffer# ' suffix = ' %*' end if bufinfo.hidden == 0 and fn.index(bufinfo.windows, vim.g.statusline_winid) >= 0 then prefix = '%#ActiveBuffer# ' suffix = ' %*' if bufinfo.changed then prefix = '%#ActiveBuffer# *' suffix = ' %*' end end return prefix .. fn.fnamemodify(fn.bufname(bufnum), ':t') .. suffix end local status_line_buffers = function() -- TODO: mark buffers with unsaved changes local active_index = -1 local acc = {} for _,bufnum in ipairs(api.nvim_list_bufs()) do local bufinfo = fn.getbufinfo(bufnum) if bufinfo.listed ~= 0 then local entry = status_line_buffer_by_num(bufnum) table.insert(acc, entry) if fn.matchstr(entry, '^%#ActiveBuffer#') then active_index = fn.index(acc, entry) end end end if active_index >= 0 then -- TODO: instead implement this as a wraparound carousel? local offset = status_line_max_length / 2 local min_buf_num = math.max(0, (active_index - offset)) local max_buf_num = math.min(#acc - 1, min_buf_num + status_line_max_length - 1) min_buf_num = math.max(0, max_buf_num - status_line_max_length + 1) local buflist = table.concat({unpack(acc, min_buf_num+1, max_buf_num+1)}, '') local prefix = '' local suffix = '' if min_buf_num > 0 then prefix = '< ' end if max_buf_num < (#acc - 1) then suffix = ' >' end return prefix .. buflist .. suffix else return table.concat(acc, '') end end function StatusLine() return status_line_buffers() .. '%*%=%c,%l/%L (%p%%)' end return { setup=function() vim.o.statusline = '%!v:lua.StatusLine()' end }