diff --git a/lua/hardline.lua b/lua/hardline.lua index 56dcd44..d480176 100644 --- a/lua/hardline.lua +++ b/lua/hardline.lua @@ -3,10 +3,9 @@ -- github.com/ojroques -------------------- VARIABLES ----------------------------- -local cmd, vim = vim.cmd, vim +local fn, cmd, vim = vim.fn, vim.cmd, 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 = {} local cache = {} @@ -30,18 +29,98 @@ M.options = { }, } +-------------------- SECTION MANAGEMENT -------------------- +local function aggregate_sections(sections) + local aggregated, pivot, stop = {}, 1 + while pivot <= #sections do + if type(sections[pivot]) == 'table' then + local items = {} + for j = pivot, #sections + 1 do + stop = j == #sections + 1 or sections[j].class ~= sections[pivot].class + if stop then + table.insert(aggregated, { + class = sections[pivot].class, + item = string.format(' %s ', table.concat(items, ' ')), + }) + pivot = j + break + end + table.insert(items, sections[j].item) + end + else + table.insert(aggregated, sections[pivot]) + pivot = pivot + 1 + end + end + return aggregated +end + +local function remove_empty_sections(sections) + local filter = function(s) + if type(s) == 'table' then return s.item ~= '' else return s ~= '' end + 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), + } + end + common.echo('WarningMsg', 'Invalid section.') + return '' + end + return vim.tbl_map(map, sections) +end + +local function remove_hidden_sections(sections) + local filter = function(s) return not s.hide or s.hide <= fn.winwidth(0) end + return vim.tbl_filter(filter, sections) +end + +-------------------- SECTION HIGHLIGHTING ------------------ +local function get_section_state(section) + if section.class == 'mode' and common.is_active() then + local mode = common.modes[fn.mode()] or common.modes['?'] + return mode.state + end + if section.class == 'bufferline' then + if section.separator then return 'separator' end + local state = section.current and 'current' or 'background' + if section.modified then state = string.format('%s_modified', state) end + return state + end + return common.is_active() and 'active' or 'inactive' +end + +local function color_section(section) + if type(section) ~= 'table' then return section end + if section.class == 'none' then return section.item end + local state = get_section_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 + -------------------- STATUSLINE ---------------------------- function M.update_statusline() local sections = cache.previous if common.is_active() or not sections then sections = M.options.sections - sections = statusline.remove_hidden_sections(sections) - sections = statusline.reload_sections(sections) - sections = statusline.remove_empty_sections(sections) - sections = statusline.aggregate_sections(sections) + sections = remove_hidden_sections(sections) + sections = reload_sections(sections) + sections = remove_empty_sections(sections) + sections = aggregate_sections(sections) cache.previous, cache.current = cache.current, sections end - return table.concat(vim.tbl_map(common.color, sections)) + return table.concat(vim.tbl_map(color_section, sections)) end -------------------- BUFFERLINE ---------------------------- @@ -53,7 +132,7 @@ function M.update_bufferline() table.insert(sections, bufferline.to_section(buffer)) if i < #buffers then table.insert(sections, separator) end end - return table.concat(vim.tbl_map(common.color, sections)) + return table.concat(vim.tbl_map(color_section, sections)) end -------------------- SETUP ----------------------------- diff --git a/lua/hardline/common.lua b/lua/hardline/common.lua index 57d17e4..2253e86 100644 --- a/lua/hardline/common.lua +++ b/lua/hardline/common.lua @@ -27,30 +27,7 @@ function M.is_active() return g.statusline_winid == fn.win_getid() end -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.separator then return 'separator' end - local state = section.current and 'current' or 'background' - if section.modified then state = string.format('%s_modified', state) end - return 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) +function M.set_cache_autocmds(augroup) cmd(string.format('augroup %s', augroup)) cmd('autocmd!') cmd(string.format('autocmd CursorHold,BufWritePost * unlet! b:%s', augroup)) diff --git a/lua/hardline/parts/whitespace.lua b/lua/hardline/parts/whitespace.lua index 0f676fd..149846a 100644 --- a/lua/hardline/parts/whitespace.lua +++ b/lua/hardline/parts/whitespace.lua @@ -49,7 +49,7 @@ end local function get_item() if not enabled then - common.set_cache('hardline_whitespace') + common.set_cache_autocmds('hardline_whitespace') enabled = true end if bo.readonly or not bo.modifiable then return '' end diff --git a/lua/hardline/parts/wordcount.lua b/lua/hardline/parts/wordcount.lua index da25b4c..00bfa20 100644 --- a/lua/hardline/parts/wordcount.lua +++ b/lua/hardline/parts/wordcount.lua @@ -33,7 +33,7 @@ end local function get_item() if not enabled then - common.set_cache('hardline_wordcount') + common.set_cache_autocmds('hardline_wordcount') enabled = true end if not vim.tbl_contains(options.filetypes, bo.filetype) then return '' end diff --git a/lua/hardline/statusline.lua b/lua/hardline/statusline.lua deleted file mode 100644 index 8f531a4..0000000 --- a/lua/hardline/statusline.lua +++ /dev/null @@ -1,63 +0,0 @@ -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 remove_empty_sections(sections) - local filter = function(s) - if type(s) == 'table' then return s.item ~= '' else return s ~= '' end - 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), - } - end - common.echo('WarningMsg', 'Invalid section.') - return '' - end - return vim.tbl_map(map, sections) -end - -local function remove_hidden_sections(sections) - local filter = function(s) return not s.hide or s.hide <= fn.winwidth(0) end - return vim.tbl_filter(filter, sections) -end - -return { - aggregate_sections = aggregate_sections, - remove_empty_sections = remove_empty_sections, - reload_sections = reload_sections, - remove_hidden_sections = remove_hidden_sections, -}