From ea75fdbb6925d3262434c715fd27bd2a1e581507 Mon Sep 17 00:00:00 2001 From: Olivier Roques Date: Sat, 26 Dec 2020 15:20:27 +0100 Subject: [PATCH] Add support for bufferline --- lua/hardline.lua | 100 +++++++++--------------------- lua/hardline/bufferline.lua | 46 ++++++++++++++ lua/hardline/common.lua | 22 ++++++- lua/hardline/parts/filename.lua | 4 +- lua/hardline/parts/whitespace.lua | 2 +- lua/hardline/parts/wordcount.lua | 2 +- lua/hardline/statusline.lua | 59 ++++++++++++++++++ lua/hardline/themes/default.lua | 32 ++++++++++ lua/hardline/themes/one.lua | 32 ++++++++++ 9 files changed, 220 insertions(+), 79 deletions(-) create mode 100644 lua/hardline/bufferline.lua create mode 100644 lua/hardline/statusline.lua diff --git a/lua/hardline.lua b/lua/hardline.lua index 47034e1..b063e1c 100644 --- a/lua/hardline.lua +++ b/lua/hardline.lua @@ -6,17 +6,20 @@ local api, cmd, fn, vim = vim.api, vim.cmd, vim.fn, vim local g, o, wo = vim.g, vim.o, vim.wo local common = require('hardline.common') +local statusline = require('hardline.statusline') +local bufferline = require('hardline.bufferline') local M = {} -------------------- OPTIONS ------------------------------- M.options = { + bufferline = false, theme = 'default', sections = { {class = 'mode', item = require('hardline.parts.mode').get_item}, {class = 'high', item = require('hardline.parts.git').get_item, hide = 80}, '%<', {class = 'med', item = require('hardline.parts.filename').get_item}, - '%=', + {class = 'med', item ='%='}, {class = 'low', item = require('hardline.parts.wordcount').get_item, hide = 80}, {class = 'error', item = require('hardline.parts.lsp').get_error}, {class = 'warning', item = require('hardline.parts.lsp').get_warning}, @@ -27,82 +30,29 @@ M.options = { } -------------------- STATUSLINE ---------------------------- -local function color_sections(sections) - local function map(section) - if type(section) ~= 'table' then return section end - if section.class == 'none' then return section.item end - local state = common.get_state(section.class) - local hlgroup = string.format('Hardline_%s_%s', section.class, state) - if fn.hlexists(hlgroup) == 0 then return section.item end - return string.format('%%#%s#%s%%*', hlgroup, section.item) - end - return vim.tbl_map(map, sections) -end - -local function aggregate_sections(sections) - local aggregated, piv = {}, 1 - while piv <= #sections do - if type(sections[piv]) == 'table' then - local items = {} - for j = piv, #sections + 1 do - if j == #sections + 1 or sections[j].class ~= sections[piv].class then - table.insert(aggregated, { - class = sections[piv].class, - item = string.format(' %s ', table.concat(items, ' ')) - }) - piv = j - break - end - table.insert(items, sections[j].item) - end - else - table.insert(aggregated, sections[piv]) - piv = piv + 1 - end - end - return aggregated -end - -local function filter_sections(sections) - local function filter(section) - if type(section) == 'table' then - return section.hide <= fn.winwidth(0) and section.item ~= '' - end - return section ~= '' - end - return vim.tbl_filter(filter, sections) -end - -local function reload_sections(sections) - local function map(section) - if type(section) == 'string' then - return section - elseif type(section) == 'function' then - return section() - elseif type(section) == 'table' then - return { - class = section.class or 'none', - item = map(section.item), - hide = section.hide or 0, - } - end - common.echo('WarningMsg', 'Invalid section.') - return '' - end - return vim.tbl_map(map, sections) -end - -function M.update() +function M.update_statusline() local cache = M.options.sections if common.is_active() then - cache = reload_sections(cache) - cache = filter_sections(cache) - cache = aggregate_sections(cache) + cache = statusline.reload_sections(cache) + cache = statusline.filter_sections(cache) + cache = statusline.aggregate_sections(cache) api.nvim_win_set_var(g.statusline_winid, 'hardline_cache', cache) else cache = api.nvim_win_get_var(g.statusline_winid, 'hardline_cache') end - return table.concat(color_sections(cache)) + return table.concat(vim.tbl_map(common.color, cache)) +end + +-------------------- BUFFERLINE ---------------------------- +function M.update_bufferline() + local sections = {} + local buffers = bufferline.get_buffers() + for _, buffer in ipairs(buffers) do + table.insert(sections, bufferline.to_section(buffer)) + table.insert(sections, {class = 'bufferline', item = '|', conceal = true}) + end + table.remove(sections) + return table.concat(vim.tbl_map(common.color, sections)) end -------------------- SETUP ----------------------------- @@ -126,15 +76,21 @@ local function set_hlgroups() end local function set_statusline() - o.statusline = [[%!luaeval('require("hardline").update()')]] + o.statusline = [[%!luaeval('require("hardline").update_statusline()')]] wo.statusline = o.statusline end +local function set_bufferline() + o.showtabline = 2 + o.tabline = [[%!luaeval('require("hardline").update_bufferline()')]] +end + function M.setup(user_options) M.options = vim.tbl_extend('force', M.options, user_options) set_theme() set_hlgroups() set_statusline() + if M.options.bufferline then set_bufferline() end end ------------------------------------------------------------ diff --git a/lua/hardline/bufferline.lua b/lua/hardline/bufferline.lua new file mode 100644 index 0000000..635a647 --- /dev/null +++ b/lua/hardline/bufferline.lua @@ -0,0 +1,46 @@ +local fn = vim.fn + +local function exclude(bufnr) + return (fn.buflisted(bufnr) == 0 or fn.getbufvar(bufnr, '&filetype') == 'qf') +end + +local function to_section(buffer) + local flags = {} + local item = buffer.name == '' and '[No Name]' or buffer.name + if buffer.flags.modified then table.insert(flags, '[+]') end + if not buffer.flags.modifiable then table.insert(flags, '[-]') end + if buffer.flags.readonly then table.insert(flags, '[RO]') end + flags = table.concat(flags) + item = flags == '' and item or string.format('%s %s', item, flags) + local section = { + class = 'bufferline', + item = string.format(' %s ', item), + modified = buffer.flags.modified, + current = buffer.current, + } + return section +end + +local function get_buffers() + local buffers = {} + for nr = 1, fn.bufnr('$') do + if not exclude(nr) then + table.insert(buffers, { + bufnr = nr, + name = fn.fnamemodify(fn.bufname(nr), ':t'), + flags = { + modified = fn.getbufvar(nr, '&modified') == 1, + modifiable = fn.getbufvar(nr, '&modifiable') == 1, + readonly = fn.getbufvar(nr, '&readonly') == 1, + }, + current = nr == fn.bufnr('%'), + }) + end + end + return buffers +end + +return { + to_section = to_section, + get_buffers = get_buffers, +} diff --git a/lua/hardline/common.lua b/lua/hardline/common.lua index 11c2e4e..a8f6add 100644 --- a/lua/hardline/common.lua +++ b/lua/hardline/common.lua @@ -1,4 +1,4 @@ -local cmd, fn, vim = vim.cmd, vim.fn, vim +local cmd, fn = vim.cmd, vim.fn local g = vim.g local M = {} @@ -27,14 +27,30 @@ function M.is_active() return g.statusline_winid == fn.win_getid() end -function M.get_state(class) - if class == 'mode' and M.is_active() then +function M.get_state(section) + if section.class == 'mode' and M.is_active() then local mode = M.modes[fn.mode()] or M.modes['?'] return mode.state end + if section.class == 'bufferline' then + if section.conceal then return 'conceal' end + local state = {} + table.insert(state, section.current and 'current' or 'background') + if section.modified then table.insert(state, 'modified') end + return table.concat(state, '_') + end return M.is_active() and 'active' or 'inactive' end +function M.color(section) + if type(section) ~= 'table' then return section end + if section.class == 'none' then return section.item end + local state = M.get_state(section) + local hlgroup = string.format('Hardline_%s_%s', section.class, state) + if fn.hlexists(hlgroup) == 0 then return section.item end + return string.format('%%#%s#%s%%*', hlgroup, section.item) +end + function M.set_cache(augroup) cmd(string.format('augroup %s', augroup)) cmd('autocmd!') diff --git a/lua/hardline/parts/filename.lua b/lua/hardline/parts/filename.lua index eaa37e4..065e384 100644 --- a/lua/hardline/parts/filename.lua +++ b/lua/hardline/parts/filename.lua @@ -6,8 +6,8 @@ local function get_name() end local function get_readonly() - if not bo.readonly then return '' end - return '[RO]' + if bo.readonly then return '[RO]' end + return '' end local function get_modified() diff --git a/lua/hardline/parts/whitespace.lua b/lua/hardline/parts/whitespace.lua index d8f5c43..b515227 100644 --- a/lua/hardline/parts/whitespace.lua +++ b/lua/hardline/parts/whitespace.lua @@ -1,4 +1,4 @@ -local cmd, fn, vim = vim.cmd, vim.fn, vim +local fn, vim = vim.fn, vim local b, bo = vim.b, vim.bo local common = require('hardline.common') diff --git a/lua/hardline/parts/wordcount.lua b/lua/hardline/parts/wordcount.lua index 89f7a11..da25b4c 100644 --- a/lua/hardline/parts/wordcount.lua +++ b/lua/hardline/parts/wordcount.lua @@ -1,4 +1,4 @@ -local cmd, fn, vim = vim.cmd, vim.fn, vim +local fn, vim = vim.fn, vim local b, bo = vim.b, vim.bo local common = require('hardline.common') diff --git a/lua/hardline/statusline.lua b/lua/hardline/statusline.lua new file mode 100644 index 0000000..e432a7d --- /dev/null +++ b/lua/hardline/statusline.lua @@ -0,0 +1,59 @@ +local fn, vim = vim.fn, vim +local common = require('hardline.common') + +local function aggregate_sections(sections) + local aggregated, piv = {}, 1 + while piv <= #sections do + if type(sections[piv]) == 'table' then + local items = {} + for j = piv, #sections + 1 do + if j == #sections + 1 or sections[j].class ~= sections[piv].class then + table.insert(aggregated, { + class = sections[piv].class, + item = string.format(' %s ', table.concat(items, ' ')) + }) + piv = j + break + end + table.insert(items, sections[j].item) + end + else + table.insert(aggregated, sections[piv]) + piv = piv + 1 + end + end + return aggregated +end + +local function filter_sections(sections) + local function filter(section) + if type(section) == 'string' then return section ~= '' end + return section.hide <= fn.winwidth(0) and section.item ~= '' + end + return vim.tbl_filter(filter, sections) +end + +local function reload_sections(sections) + local function map(section) + if type(section) == 'string' then + return section + elseif type(section) == 'function' then + return section() + elseif type(section) == 'table' then + return { + class = section.class or 'none', + item = map(section.item), + hide = section.hide or 0, + } + end + common.echo('WarningMsg', 'Invalid section.') + return '' + end + return vim.tbl_map(map, sections) +end + +return { + aggregate_sections = aggregate_sections, + filter_sections = filter_sections, + reload_sections = reload_sections, +} diff --git a/lua/hardline/themes/default.lua b/lua/hardline/themes/default.lua index 917d846..59818ba 100644 --- a/lua/hardline/themes/default.lua +++ b/lua/hardline/themes/default.lua @@ -91,4 +91,36 @@ return { }, inactive = inactive, }, + bufferline = { + conceal = { + guifg = colors.comment_grey.gui, + guibg = colors.black.gui, + ctermfg = colors.comment_grey.cterm, + ctermbg = colors.black.cterm, + }, + current = { + guifg = colors.black.gui, + guibg = colors.green.gui, + ctermfg = colors.black.cterm, + ctermbg = colors.green.cterm, + }, + current_modified = { + guifg = colors.black.gui, + guibg = colors.blue.gui, + ctermfg = colors.black.cterm, + ctermbg = colors.blue.cterm, + }, + background = { + guifg = colors.green.gui, + guibg = colors.black.gui, + ctermfg = colors.green.cterm, + ctermbg = colors.black.cterm, + }, + background_modified = { + guifg = colors.blue.gui, + guibg = colors.black.gui, + ctermfg = colors.blue.cterm, + ctermbg = colors.black.cterm, + }, + }, } diff --git a/lua/hardline/themes/one.lua b/lua/hardline/themes/one.lua index 917d846..59818ba 100644 --- a/lua/hardline/themes/one.lua +++ b/lua/hardline/themes/one.lua @@ -91,4 +91,36 @@ return { }, inactive = inactive, }, + bufferline = { + conceal = { + guifg = colors.comment_grey.gui, + guibg = colors.black.gui, + ctermfg = colors.comment_grey.cterm, + ctermbg = colors.black.cterm, + }, + current = { + guifg = colors.black.gui, + guibg = colors.green.gui, + ctermfg = colors.black.cterm, + ctermbg = colors.green.cterm, + }, + current_modified = { + guifg = colors.black.gui, + guibg = colors.blue.gui, + ctermfg = colors.black.cterm, + ctermbg = colors.blue.cterm, + }, + background = { + guifg = colors.green.gui, + guibg = colors.black.gui, + ctermfg = colors.green.cterm, + ctermbg = colors.black.cterm, + }, + background_modified = { + guifg = colors.blue.gui, + guibg = colors.black.gui, + ctermfg = colors.blue.cterm, + ctermbg = colors.black.cterm, + }, + }, }