diff --git a/.luacov b/.luacov index 1684712..b07e6fb 100644 --- a/.luacov +++ b/.luacov @@ -15,6 +15,6 @@ return { }, statsfile = 'luacov.stats', reportfile = 'luacov.report', - includeuntestedfiles = true, + -- includeuntestedfiles = true, } -- vim:ft=lua diff --git a/lua/lualine/components/tabs/tab.lua b/lua/lualine/components/tabs/tab.lua index 979f8da..dbfdd4a 100644 --- a/lua/lualine/components/tabs/tab.lua +++ b/lua/lualine/components/tabs/tab.lua @@ -19,7 +19,8 @@ end --- of the tab. ---@return string function Tab:label() - local custom_tabname = vim.t[self.tabId].tabname + local ok,custom_tabname = pcall(vim.api.nvim_tabpage_get_var, self.tabId, 'tabname') + if not ok then custom_tabname = nil end if custom_tabname and custom_tabname ~= '' then return modules.utils.stl_escape(custom_tabname) end diff --git a/lua/tests/helpers.lua b/lua/tests/helpers.lua index ab7d4af..0ee1ae7 100644 --- a/lua/tests/helpers.lua +++ b/lua/tests/helpers.lua @@ -73,4 +73,27 @@ M.P = function(t) print(vim.inspect(t)) end +function M.dedent(str, leave_indent) + -- find minimum common indent across lines + local indent = nil + for line in str:gmatch('[^\n]+') do + local line_indent = line:match('^%s+') or '' + if indent == nil or #line_indent < #indent then + indent = line_indent + end + end + if indent == nil or #indent == 0 then + -- no minimum common indent + return str + end + local left_indent = (' '):rep(leave_indent or 0) + -- create a pattern for the indent + indent = indent:gsub('%s', '[ \t]') + -- strip it from the first line + str = str:gsub('^' .. indent, left_indent) + -- strip it from the remaining lines + str = str:gsub('[\n]' .. indent, '\n' .. left_indent) + return str +end + return M diff --git a/lua/tests/spec/component_spec.lua b/lua/tests/spec/component_spec.lua index 83cb81f..f5fbe84 100644 --- a/lua/tests/spec/component_spec.lua +++ b/lua/tests/spec/component_spec.lua @@ -568,7 +568,7 @@ describe('Branch component', function() local tmpdir local file local git = function(...) - return vim.fn.system('git -C ' .. tmpdir .. ' ' .. string.format(...)) + return vim.fn.system("git -c user.name='asdf' -c user.email='asdf@jlk.org' -C " .. tmpdir .. ' ' .. string.format(...)) end local assert_comp_ins = helpers.assert_component_instence @@ -604,20 +604,19 @@ describe('Branch component', function() assert_comp_ins(branch_comp, 'test_branch2') end) - -- TODO: Figure out why this test fails in CI - -- it('works in detached head mode', function() - -- local opts = build_component_opts { - -- component_separators = { left = '', right = '' }, - -- icons_enabled = false, - -- padding = 0, - -- } - -- git 'checkout -b test_branch2' - -- git 'commit --allow-empty -m "test commit1"' - -- git 'commit --allow-empty -m "test commit2"' - -- git 'commit --allow-empty -m "test commit3"' - -- git('checkout HEAD~1') - -- vim.cmd('e ' .. file) - -- local rev = git('rev-parse --short=6 HEAD'):sub(1, 6) - -- assert_component('branch', opts, rev) - -- end) + it('works in detached head mode', function() + local opts = build_component_opts { + component_separators = { left = '', right = '' }, + icons_enabled = false, + padding = 0, + } + git 'checkout -b test_branch2' + git 'commit --allow-empty -m "test commit1"' + git 'commit --allow-empty -m "test commit2"' + git 'commit --allow-empty -m "test commit3"' + git('checkout HEAD~1') + vim.cmd('e ' .. file) + local rev = git('rev-parse --short=6 HEAD'):sub(1, 6) + assert_component('branch', opts, rev) + end) end) diff --git a/lua/tests/spec/lualine_spec.lua b/lua/tests/spec/lualine_spec.lua index 2546d2c..42f7d98 100644 --- a/lua/tests/spec/lualine_spec.lua +++ b/lua/tests/spec/lualine_spec.lua @@ -2,74 +2,92 @@ -- MIT license, see LICENSE for more details. local eq = assert.are.same +local statusline = require('tests.statusline').new(120, 'active') +local inactive_statusline = statusline.new(120, 'inactive') +local tabline = statusline.new(120, 'tabline') describe('Lualine', function() - local utils = require('lualine.utils.utils') - local lualine_focused = true - utils.is_focused = function() - return lualine_focused - end - - local config = { - options = { - icons_enabled = true, - theme = 'gruvbox', - component_separators = { left = '', right = '' }, - section_separators = { left = '', right = '' }, - disabled_filetypes = {}, - always_divide_middle = true, - }, - sections = { - lualine_a = { 'mode' }, - -- We can't test branch component inside lualines repo. - -- As branch name will differ in pr/CI. We could setup a dummy repo - -- but plenary doesn't yet support setup() & teardown() so replacing - -- branch with a dummy component. - lualine_b = { - { - function() - return 'master' - end, - icon = '', - }, - 'diagnostics', - }, - lualine_c = { 'filename' }, - lualine_x = { 'encoding', 'fileformat', 'filetype' }, - lualine_y = { 'progress' }, - lualine_z = { 'location' }, - }, - inactive_sections = { - lualine_a = {}, - lualine_b = {}, - lualine_c = { 'filename' }, - lualine_x = { 'location' }, - lualine_y = {}, - lualine_z = {}, - }, - tabline = {}, - extensions = {}, - } + local config before_each(function() + config = { + options = { + icons_enabled = true, + theme = 'gruvbox', + component_separators = { left = '', right = '' }, + section_separators = { left = '', right = '' }, + disabled_filetypes = {}, + always_divide_middle = true, + }, + sections = { + lualine_a = { 'mode' }, + -- We can't test branch component inside lualines repo. + -- As branch name will differ in pr/CI. We could setup a dummy repo + -- but plenary doesn't yet support setup() & teardown() so replacing + -- branch with a dummy component. + lualine_b = { + { + function() + return 'master' + end, + icon = '', + }, + 'diagnostics', + }, + lualine_c = { 'filename' }, + lualine_x = { 'encoding', 'fileformat', 'filetype' }, + lualine_y = { 'progress' }, + lualine_z = { 'location' }, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = { 'filename' }, + lualine_x = { 'location' }, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + extensions = {}, + } + + vim.opt.swapfile = false vim.cmd('bufdo bdelete') pcall(vim.cmd, 'tabdo tabclose') - lualine_focused = true require('lualine').setup(config) end) it('shows active statusline', function() - eq( - '%#lualine_a_normal# NORMAL %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_b_normal#  master %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%<%#lualine_c_normal# [No Name] %#lualine_c_normal#%=%#lualine_c_normal#  %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%#lualine_b_normal# %3p%% %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_a_normal# %3l:%-2v ', - require('lualine').statusline() - ) + statusline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_normal_to_lualine_b_normal = { bg = "#504945", fg = "#a89984" } + 3: lualine_b_normal = { bg = "#504945", fg = "#ebdbb2" } + 4: lualine_transitional_lualine_b_normal_to_lualine_c_normal = { bg = "#3c3836", fg = "#504945" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: NORMAL } + {2:} + {3:  master } + {4:} + {5: [No Name] } + {5: } + {5:  } + {4:} + {3: 100% } + {2:} + {1: 0:1 }| + ]===]) end) it('shows inactive statusline', function() - lualine_focused = false - eq( - '%<%#lualine_c_inactive# [No Name] %#lualine_c_inactive#%=%#lualine_c_inactive# %3l:%-2v ', - require('lualine').statusline() - ) + inactive_statusline:expect([===[ + highlights = { + 1: lualine_c_inactive = { bg = "#3c3836", fg = "#a89984" } + } + |{1: [No Name] } + {1: } + {1: 0:1 }| + ]===]) end) it('get_config can retrive config', function() @@ -80,80 +98,161 @@ describe('Lualine', function() local conf = require('lualine').get_config() conf.sections.lualine_a = {} require('lualine').setup(conf) - eq( - '%#lualine_b_normal#  master %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%<%#lualine_c_normal# [No Name] %#lualine_c_normal#%=%#lualine_c_normal#  %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%#lualine_b_normal# %3p%% %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_a_normal# %3l:%-2v ', - require('lualine').statusline() - ) + statusline:expect([===[ + highlights = { + 1: lualine_b_normal = { bg = "#504945", fg = "#ebdbb2" } + 2: lualine_transitional_lualine_b_normal_to_lualine_c_normal = { bg = "#3c3836", fg = "#504945" } + 3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 4: lualine_transitional_lualine_a_normal_to_lualine_b_normal = { bg = "#504945", fg = "#a89984" } + 5: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + } + |{1:  master } + {2:} + {3: [No Name] } + {3: } + {3:  } + {2:} + {1: 100% } + {4:} + {5: 0:1 }| + ]===]) end) it('Can work without section separators', function() - local conf = vim.deepcopy(config) - conf.options.section_separators = '' - require('lualine').setup(conf) - eq( - '%#lualine_a_normal# NORMAL %#lualine_b_normal#  master %<%#lualine_c_normal# [No Name] %#lualine_c_normal#%=%#lualine_c_normal#  %#lualine_b_normal# %3p%% %#lualine_a_normal# %3l:%-2v ', - require('lualine').statusline() - ) + config.options.section_separators = '' + require('lualine').setup(config) + statusline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_b_normal = { bg = "#504945", fg = "#ebdbb2" } + 3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: NORMAL } + {2:  master } + {3: [No Name] } + {3: } + {3:  } + {2: 100% } + {1: 0:1 }| + ]===]) end) it('Can work without component_separators', function() - local conf = vim.deepcopy(config) - table.insert(conf.sections.lualine_a, function() + table.insert(config.sections.lualine_a, function() return 'test_comp1' end) - table.insert(conf.sections.lualine_z, function() + table.insert(config.sections.lualine_z, function() return 'test_comp2' end) - require('lualine').setup(conf) - eq( - '%#lualine_a_normal# NORMAL %#lualine_a_normal# test_comp1 %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_b_normal#  master %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%<%#lualine_c_normal# [No Name] %#lualine_c_normal#%=%#lualine_c_normal#  %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%#lualine_b_normal# %3p%% %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_a_normal# %3l:%-2v %#lualine_a_normal# test_comp2 ', - require('lualine').statusline() - ) - conf.options.component_separators = '' - require('lualine').setup(conf) - eq( - '%#lualine_a_normal# NORMAL %#lualine_a_normal# test_comp1 %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_b_normal#  master %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%<%#lualine_c_normal# [No Name] %#lualine_c_normal#%=%#lualine_c_normal#  %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%#lualine_b_normal# %3p%% %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_a_normal# %3l:%-2v %#lualine_a_normal# test_comp2 ', - require('lualine').statusline() - ) + + require('lualine').setup(config) + statusline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_normal_to_lualine_b_normal = { bg = "#504945", fg = "#a89984" } + 3: lualine_b_normal = { bg = "#504945", fg = "#ebdbb2" } + 4: lualine_transitional_lualine_b_normal_to_lualine_c_normal = { bg = "#3c3836", fg = "#504945" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: NORMAL } + {1: test_comp1 } + {2:} + {3:  master } + {4:} + {5: [No Name] } + {5: } + {5:  } + {4:} + {3: 100% } + {2:} + {1: 0:1 } + {1: test_comp2 }| + ]===]) + + config.options.component_separators = '' + require('lualine').setup(config) + statusline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_normal_to_lualine_b_normal = { bg = "#504945", fg = "#a89984" } + 3: lualine_b_normal = { bg = "#504945", fg = "#ebdbb2" } + 4: lualine_transitional_lualine_b_normal_to_lualine_c_normal = { bg = "#3c3836", fg = "#504945" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: NORMAL } + {1: test_comp1 } + {2:} + {3:  master } + {4:} + {5: [No Name] } + {5: } + {5:  } + {4:} + {3: 100% } + {2:} + {1: 0:1 } + {1: test_comp2 }| + ]===]) end) it('mid divider can be disbled on special case', function() - local conf = vim.deepcopy(config) - conf.options.always_divide_middle = false - conf.sections.lualine_x = {} - conf.sections.lualine_y = {} - conf.sections.lualine_z = {} - require('lualine').setup(conf) - eq( - '%#lualine_a_normal# NORMAL %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_b_normal#  master %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%<%#lualine_c_normal# [No Name] ', - require('lualine').statusline(true) - ) + config.options.always_divide_middle = false + config.sections.lualine_x = {} + config.sections.lualine_y = {} + config.sections.lualine_z = {} + require('lualine').setup(config) + statusline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_normal_to_lualine_b_normal = { bg = "#504945", fg = "#a89984" } + 3: lualine_b_normal = { bg = "#504945", fg = "#ebdbb2" } + 4: lualine_transitional_lualine_b_normal_to_lualine_c_normal = { bg = "#3c3836", fg = "#504945" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: NORMAL } + {2:} + {3:  master } + {4:} + {5: [No Name] }| + ]===]) end) it('works with icons disabled', function() - local conf = vim.deepcopy(config) - conf.options.icons_enabled = false - conf.options.section_separators = '' - require('lualine').setup(conf) - eq( - '%#lualine_a_normal# NORMAL %#lualine_b_normal# master %<%#lualine_c_normal# [No Name] %#lualine_c_normal#%=%#lualine_c_normal# unix %#lualine_b_normal# %3p%% %#lualine_a_normal# %3l:%-2v ', - require('lualine').statusline(true) - ) + config.options.icons_enabled = false + config.options.section_separators = '' + require('lualine').setup(config) + statusline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_b_normal = { bg = "#504945", fg = "#ebdbb2" } + 3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: NORMAL } + {2: master } + {3: [No Name] } + {3: } + {3: unix } + {2: 100% } + {1: 0:1 }| + ]===]) end) it('can be desabled for specific filetypes', function() - local conf = vim.deepcopy(config) - conf.options.disabled_filetypes = { 'test_ft' } - require('lualine').setup(conf) + config.options.disabled_filetypes = { 'test_ft' } + require('lualine').setup(config) local old_ft = vim.bo.ft vim.bo.ft = 'test_ft' - eq('', require('lualine').statusline(true)) + statusline:expect([===[ + highlights = { + 1: StatusLine = { bold = true, reverse = true } + } + || + ]===]) vim.bo.ft = old_ft end) it('can apply custom extensions', function() - local conf = vim.deepcopy(config) - table.insert(conf.extensions, { + table.insert(config.extensions, { filetypes = { 'test_ft' }, sections = { lualine_a = { @@ -165,17 +264,22 @@ describe('Lualine', function() }) local old_ft = vim.bo.ft vim.bo.ft = 'test_ft' - require('lualine').setup(conf) - eq( - '%#lualine_a_normal# custom_extension_component %#lualine_transitional_lualine_a_normal_to_lualine_c_normal#%#lualine_c_normal#%=', - require('lualine').statusline(true) - ) + require('lualine').setup(config) + statusline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_normal_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: custom_extension_component } + {2:} + {3: }| + ]===]) vim.bo.ft = old_ft end) it('same extension can be applied to multiple filetypes', function() - local conf = vim.deepcopy(config) - table.insert(conf.extensions, { + table.insert(config.extensions, { filetypes = { 'test_ft1', 'test_ft2' }, sections = { lualine_a = { @@ -187,226 +291,465 @@ describe('Lualine', function() }) local old_ft = vim.bo.ft vim.bo.ft = 'test_ft1' - require('lualine').setup(conf) - eq( - '%#lualine_a_normal# custom_extension_component %#lualine_transitional_lualine_a_normal_to_lualine_c_normal#%#lualine_c_normal#%=', - require('lualine').statusline() - ) + require('lualine').setup(config) + statusline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_normal_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: custom_extension_component } + {2:} + {3: }| + ]===]) vim.bo.ft = old_ft - eq( - '%#lualine_a_normal# NORMAL %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_b_normal#  master %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%<%#lualine_c_normal# [No Name] %#lualine_c_normal#%=%#lualine_c_normal#  %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%#lualine_b_normal# %3p%% %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_a_normal# %3l:%-2v ', - require('lualine').statusline() - ) + statusline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_normal_to_lualine_b_normal = { bg = "#504945", fg = "#a89984" } + 3: lualine_b_normal = { bg = "#504945", fg = "#ebdbb2" } + 4: lualine_transitional_lualine_b_normal_to_lualine_c_normal = { bg = "#3c3836", fg = "#504945" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: NORMAL } + {2:} + {3:  master } + {4:} + {5: [No Name] } + {5: } + {5:  } + {4:} + {3: 100% } + {2:} + {1: 0:1 }| + ]===]) + vim.bo.ft = 'test_ft2' - eq( - '%#lualine_a_normal# custom_extension_component %#lualine_transitional_lualine_a_normal_to_lualine_c_normal#%#lualine_c_normal#%=', - require('lualine').statusline() - ) + statusline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_normal_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: custom_extension_component } + {2:} + {3: }| + ]===]) vim.bo.ft = old_ft end) -- TODO: figure put why some of the tablines tests fail in CI - -- describe('tabline', function() - -- local tab_conf = vim.deepcopy(config) - -- tab_conf.tabline = { - -- lualine_a = { - -- function() - -- return 'tabline_component' - -- end, - -- }, - -- lualine_b = {}, - -- lualine_c = {}, - -- lualine_x = {}, - -- lualine_y = {}, - -- lualine_z = {}, - -- } - -- - -- it('can use tabline', function() - -- local conf = vim.deepcopy(tab_conf) - -- conf.tabline.lualine_a = { - -- function() - -- return 'tabline_component' - -- end, - -- } - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq( - -- '%#lualine_a_normal# tabline_component %#lualine_transitional_lualine_a_normal_to_lualine_c_normal#%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- end) - -- - -- it('can use tabline as statusline', function() - -- local conf = vim.deepcopy(config) - -- conf.tabline = conf.sections - -- conf.sections = {} - -- conf.inactive_sections = {} - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq('', vim.go.statusline) - -- eq( - -- '%#lualine_a_normal# NORMAL %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_b_normal#  master %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%<%#lualine_c_normal# [No Name] %#lualine_c_normal#%=%#lualine_c_normal#  %#lualine_transitional_lualine_b_normal_to_lualine_c_normal#%#lualine_b_normal# %3p%% %#lualine_transitional_lualine_a_normal_to_lualine_b_normal#%#lualine_a_normal# %3l:%-2v ', - -- require('lualine').tabline() - -- ) - -- end) - -- describe('tabs component', function() - -- it('works', function() - -- local conf = vim.deepcopy(tab_conf) - -- conf.tabline.lualine_a = { { 'tabs', max_length = 1e3 } } - -- vim.cmd 'tabnew' - -- vim.cmd 'tabnew' - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq( - -- '%#lualine_tabs_active_0_no_mode#%1@LualineSwitchTab@ 1 %T%#lualine_tabs_active_0_no_mode#%2@LualineSwitchTab@ 2 %T%#lualine_transitional_lualine_tabs_active_0_no_mode_to_lualine_tabs_active_no_mode#%#lualine_tabs_active_no_mode#%3@LualineSwitchTab@ 3 %T%#lualine_transitional_lualine_tabs_active_no_mode_to_lualine_c_normal#%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- vim.cmd 'tabprev' - -- eq( - -- '%#lualine_tabs_active_0_no_mode#%1@LualineSwitchTab@ 1 %T%#lualine_transitional_lualine_tabs_active_0_no_mode_to_lualine_tabs_active_no_mode#%#lualine_tabs_active_no_mode#%2@LualineSwitchTab@ 2 %T%#lualine_transitional_lualine_tabs_active_no_mode_to_lualine_tabs_active_0_no_mode#%#lualine_tabs_active_0_no_mode#%3@LualineSwitchTab@ 3 %T%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- vim.cmd 'tabprev' - -- eq( - -- '%#lualine_tabs_active_no_mode#%1@LualineSwitchTab@ 1 %T%#lualine_transitional_lualine_tabs_active_no_mode_to_lualine_tabs_active_0_no_mode#%#lualine_tabs_active_0_no_mode#%2@LualineSwitchTab@ 2 %T%#lualine_tabs_active_0_no_mode#%3@LualineSwitchTab@ 3 %T%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- end) - -- it('mode option can change layout', function() - -- local conf = vim.deepcopy(tab_conf) - -- conf.tabline.lualine_a = { { 'tabs', max_length = 1e3, mode = 0 } } - -- vim.cmd('tabe ' .. 'a.txt') - -- vim.cmd('tabe ' .. 'b.txt') - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq( - -- '%#lualine_tabs_active_0_no_mode#%1@LualineSwitchTab@ 1 %T%#lualine_tabs_active_0_no_mode#%2@LualineSwitchTab@ 2 %T%#lualine_transitional_lualine_tabs_active_0_no_mode_to_lualine_tabs_active_no_mode#%#lualine_tabs_active_no_mode#%3@LualineSwitchTab@ 3 %T%#lualine_transitional_lualine_tabs_active_no_mode_to_lualine_c_normal#%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- conf.tabline.lualine_a = { { 'tabs', max_length = 1e3, mode = 1 } } - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq( - -- '%#lualine_tabs_active_0_no_mode#%1@LualineSwitchTab@ [No Name] %T%#lualine_tabs_active_0_no_mode#%2@LualineSwitchTab@ a.txt %T%#lualine_transitional_lualine_tabs_active_0_no_mode_to_lualine_tabs_active_no_mode#%#lualine_tabs_active_no_mode#%3@LualineSwitchTab@ b.txt %T%#lualine_transitional_lualine_tabs_active_no_mode_to_lualine_c_normal#%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- conf.tabline.lualine_a = { { 'tabs', max_length = 1e3, mode = 2 } } - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq( - -- '%#lualine_tabs_active_0_no_mode#%1@LualineSwitchTab@ 1 [No Name] %T%#lualine_tabs_active_0_no_mode#%2@LualineSwitchTab@ 2 a.txt %T%#lualine_transitional_lualine_tabs_active_0_no_mode_to_lualine_tabs_active_no_mode#%#lualine_tabs_active_no_mode#%3@LualineSwitchTab@ 3 b.txt %T%#lualine_transitional_lualine_tabs_active_no_mode_to_lualine_c_normal#%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- end) - -- end) - -- - -- describe('buffers component', function() - -- it('works', function() - -- local conf = vim.deepcopy(tab_conf) - -- conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, icons_enabled = false } } - -- vim.cmd('tabe ' .. 'a.txt') - -- vim.cmd('tabe ' .. 'b.txt') - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq( - -- '%#lualine_buffers_active_0_no_mode#%4@LualineSwitchBuffer@ a.txt %T%#lualine_transitional_lualine_buffers_active_0_no_mode_to_lualine_buffers_active_no_mode#%#lualine_buffers_active_no_mode#%5@LualineSwitchBuffer@ b.txt %T%#lualine_transitional_lualine_buffers_active_no_mode_to_lualine_buffers_active_0_no_mode#%#lualine_buffers_active_0_no_mode#%6@LualineSwitchBuffer@ [No Name] %T%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- vim.cmd 'tabprev' - -- eq( - -- '%#lualine_buffers_active_no_mode#%4@LualineSwitchBuffer@ a.txt %T%#lualine_transitional_lualine_buffers_active_no_mode_to_lualine_buffers_active_0_no_mode#%#lualine_buffers_active_0_no_mode#%5@LualineSwitchBuffer@ b.txt %T%#lualine_buffers_active_0_no_mode#%6@LualineSwitchBuffer@ [No Name] %T%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- vim.cmd 'tabprev' - -- eq( - -- '%#lualine_buffers_active_0_no_mode#%4@LualineSwitchBuffer@ a.txt %T%#lualine_buffers_active_0_no_mode#%5@LualineSwitchBuffer@ b.txt %T%#lualine_transitional_lualine_buffers_active_0_no_mode_to_lualine_buffers_active_no_mode#%#lualine_buffers_active_no_mode#%6@LualineSwitchBuffer@ [No Name] %T%#lualine_transitional_lualine_buffers_active_no_mode_to_lualine_c_normal#%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- end) - -- it('mode option can change layout', function() - -- local conf = vim.deepcopy(tab_conf) - -- conf.tabline.lualine_a = { { 'tabs', max_length = 1e3, mode = 0, icons_enabled = false } } - -- vim.cmd('tabe ' .. 'a.txt') - -- vim.cmd('tabe ' .. 'b.txt') - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq( - -- '%#lualine_tabs_active_0_no_mode#%1@LualineSwitchTab@ 1 %T%#lualine_tabs_active_0_no_mode#%2@LualineSwitchTab@ 2 %T%#lualine_transitional_lualine_tabs_active_0_no_mode_to_lualine_tabs_active_no_mode#%#lualine_tabs_active_no_mode#%3@LualineSwitchTab@ 3 %T%#lualine_transitional_lualine_tabs_active_no_mode_to_lualine_c_normal#%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, mode = 1, icons_enabled = false } } - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq( - -- '%#lualine_buffers_active_0_no_mode#%4@LualineSwitchBuffer@ 4 %T%#lualine_transitional_lualine_buffers_active_0_no_mode_to_lualine_buffers_active_no_mode#%#lualine_buffers_active_no_mode#%5@LualineSwitchBuffer@ 5 %T%#lualine_transitional_lualine_buffers_active_no_mode_to_lualine_buffers_active_0_no_mode#%#lualine_buffers_active_0_no_mode#%6@LualineSwitchBuffer@ 6 %T%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, mode = 2, icons_enabled = false } } - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq( - -- '%#lualine_buffers_active_0_no_mode#%4@LualineSwitchBuffer@ 4 a.txt %T%#lualine_transitional_lualine_buffers_active_0_no_mode_to_lualine_buffers_active_no_mode#%#lualine_buffers_active_no_mode#%5@LualineSwitchBuffer@ 5 b.txt %T%#lualine_transitional_lualine_buffers_active_no_mode_to_lualine_buffers_active_0_no_mode#%#lualine_buffers_active_0_no_mode#%6@LualineSwitchBuffer@ 6 [No Name] %T%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- end) - -- - -- it('can show modified status', function() - -- local conf = vim.deepcopy(tab_conf) - -- conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, show_modified_status = true, icons_enabled = false } } - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq( - -- '%#lualine_buffers_active_no_mode#%6@LualineSwitchBuffer@ [No Name] %T%#lualine_transitional_lualine_buffers_active_no_mode_to_lualine_c_normal#%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- vim.bo.modified = true - -- eq( - -- '%#lualine_buffers_active_no_mode#%6@LualineSwitchBuffer@ [No Name] + %T%#lualine_transitional_lualine_buffers_active_no_mode_to_lualine_c_normal#%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- vim.bo.modified = false - -- end) - -- - -- it('can show relative path', function() - -- local conf = vim.deepcopy(tab_conf) - -- conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, show_filename_only = false, icons_enabled = false } } - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- vim.cmd('e ' .. os.tmpname()) - -- eq( - -- '%#lualine_buffers_active_no_mode#%6@LualineSwitchBuffer@ ' - -- .. vim.fn.pathshorten(vim.fn.expand '%:p:.') - -- .. ' %T%#lualine_transitional_lualine_buffers_active_no_mode_to_lualine_c_normal#%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- end) - -- - -- it('can show ellipsis when max_width is crossed', function() - -- local conf = vim.deepcopy(tab_conf) - -- conf.tabline.lualine_a = { { 'buffers', max_length = 1 } } - -- vim.cmd 'tabe a.txt' - -- vim.cmd 'tabe b.txt' - -- vim.cmd 'tabprev' - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- eq( - -- '%#lualine_buffers_active_no_mode#%4@LualineSwitchBuffer@ a.txt %T%#lualine_transitional_lualine_buffers_active_no_mode_to_lualine_buffers_active_0_no_mode#%#lualine_buffers_active_0_no_mode#%5@LualineSwitchBuffer@ ... %T%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- end) - -- - -- it('can show filetype icons', function() - -- local conf = vim.deepcopy(tab_conf) - -- conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, show_filename_only = false } } - -- require('lualine').setup(conf) - -- require('lualine').statusline() - -- vim.cmd('e t.lua') - -- eq( - -- '%#lualine_buffers_active_no_mode#%7@LualineSwitchBuffer@  t.lua %T%#lualine_transitional_lualine_buffers_active_no_mode_to_lualine_c_normal#%#lualine_c_normal#%=', - -- require('lualine').tabline() - -- ) - -- end) - -- - -- end) - -- end) + describe('tabline', function() + local tab_conf = vim.deepcopy(config) + tab_conf.tabline = { + lualine_a = { + function() + return 'tabline_component' + end, + }, + lualine_b = {}, + lualine_c = {}, + lualine_x = {}, + lualine_y = {}, + lualine_z = {}, + } + + it('can use tabline', function() + local conf = vim.deepcopy(tab_conf) + conf.tabline.lualine_a = { + function() + return 'tabline_component' + end, + } + require('lualine').setup(conf) + require('lualine').statusline() + tabline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_normal_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: tabline_component } + {2:} + {3: }| + ]===]) + end) + + it('can use tabline as statusline', function() + local conf = vim.deepcopy(config) + conf.tabline = conf.sections + conf.sections = {} + conf.inactive_sections = {} + require('lualine').setup(conf) + require('lualine').statusline() + eq('', vim.go.statusline) + + tabline:expect([===[ + highlights = { + 1: lualine_a_normal = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_normal_to_lualine_b_normal = { bg = "#504945", fg = "#a89984" } + 3: lualine_b_normal = { bg = "#504945", fg = "#ebdbb2" } + 4: lualine_transitional_lualine_b_normal_to_lualine_c_normal = { bg = "#3c3836", fg = "#504945" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: NORMAL } + {2:} + {3:  master } + {4:} + {5: [No Name] } + {5: } + {5:  } + {4:} + {3: 100% } + {2:} + {1: 0:1 }| + ]===]) + end) + describe('tabs component', function() + it('works', function() + local conf = vim.deepcopy(tab_conf) + conf.tabline.lualine_a = { { 'tabs', max_length = 1e3 } } + vim.cmd('tabnew') + vim.cmd('tabnew') + require('lualine').setup(conf) + require('lualine').statusline() + tabline:expect([===[ + highlights = { + 1: lualine_a_tabs_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 2: lualine_transitional_lualine_a_tabs_inactive_to_lualine_a_tabs_active = { bg = "#a89984", fg = "#3c3836" } + 3: lualine_a_tabs_active = { bg = "#a89984", bold = true, fg = "#282828" } + 4: lualine_transitional_lualine_a_tabs_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: 1 } + {1: 2 } + {2:} + {3: 3 } + {4:} + {5: }| + ]===]) + + vim.cmd('tabprev') + tabline:expect([===[ + highlights = { + 1: lualine_a_tabs_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 2: lualine_transitional_lualine_a_tabs_inactive_to_lualine_a_tabs_active = { bg = "#a89984", fg = "#3c3836" } + 3: lualine_a_tabs_active = { bg = "#a89984", bold = true, fg = "#282828" } + 4: lualine_transitional_lualine_a_tabs_active_to_lualine_a_tabs_inactive = { bg = "#3c3836", fg = "#a89984" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: 1 } + {2:} + {3: 2 } + {4:} + {1: 3 } + {5: }| + ]===]) + + vim.cmd('tabprev') + tabline:expect([===[ + highlights = { + 1: lualine_a_tabs_active = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_tabs_active_to_lualine_a_tabs_inactive = { bg = "#3c3836", fg = "#a89984" } + 3: lualine_a_tabs_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 4: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: 1 } + {2:} + {3: 2 } + {3: 3 } + {4: }| + ]===]) + end) + + it('mode option can change layout', function() + local conf = vim.deepcopy(tab_conf) + conf.tabline.lualine_a = { { 'tabs', max_length = 1e3, mode = 0 } } + vim.cmd('tabe ' .. 'a.txt') + vim.cmd('tabe ' .. 'b.txt') + require('lualine').setup(conf) + require('lualine').statusline() + tabline:expect([===[ + highlights = { + 1: lualine_a_tabs_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 2: lualine_transitional_lualine_a_tabs_inactive_to_lualine_a_tabs_active = { bg = "#a89984", fg = "#3c3836" } + 3: lualine_a_tabs_active = { bg = "#a89984", bold = true, fg = "#282828" } + 4: lualine_transitional_lualine_a_tabs_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: 1 } + {1: 2 } + {2:} + {3: 3 } + {4:} + {5: }| + ]===]) + + tabline:expect([===[ + highlights = { + 1: lualine_a_tabs_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 2: lualine_transitional_lualine_a_tabs_inactive_to_lualine_a_tabs_active = { bg = "#a89984", fg = "#3c3836" } + 3: lualine_a_tabs_active = { bg = "#a89984", bold = true, fg = "#282828" } + 4: lualine_transitional_lualine_a_tabs_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: 1 } + {1: 2 } + {2:} + {3: 3 } + {4:} + {5: }| + ]===]) + + conf.tabline.lualine_a = { { 'tabs', max_length = 1e3, mode = 1 } } + require('lualine').setup(conf) + require('lualine').statusline() + tabline:expect([===[ + highlights = { + 1: lualine_a_tabs_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 2: lualine_transitional_lualine_a_tabs_inactive_to_lualine_a_tabs_active = { bg = "#a89984", fg = "#3c3836" } + 3: lualine_a_tabs_active = { bg = "#a89984", bold = true, fg = "#282828" } + 4: lualine_transitional_lualine_a_tabs_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: [No Name] } + {1: a.txt } + {2:} + {3: b.txt } + {4:} + {5: }| + ]===]) + + conf.tabline.lualine_a = { { 'tabs', max_length = 1e3, mode = 2 } } + require('lualine').setup(conf) + require('lualine').statusline() + tabline:expect([===[ + highlights = { + 1: lualine_a_tabs_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 2: lualine_transitional_lualine_a_tabs_inactive_to_lualine_a_tabs_active = { bg = "#a89984", fg = "#3c3836" } + 3: lualine_a_tabs_active = { bg = "#a89984", bold = true, fg = "#282828" } + 4: lualine_transitional_lualine_a_tabs_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: 1 [No Name] } + {1: 2 a.txt } + {2:} + {3: 3 b.txt } + {4:} + {5: }| + ]===]) + end) + end) + + describe('buffers component', function() + it('works', function() + local conf = vim.deepcopy(tab_conf) + conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, icons_enabled = false } } + vim.cmd('tabe ' .. 'a.txt') + vim.cmd('tabe ' .. 'b.txt') + require('lualine').setup(conf) + require('lualine').statusline() + tabline:expect([===[ + highlights = { + 1: lualine_a_buffers_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 2: lualine_transitional_lualine_a_buffers_inactive_to_lualine_a_buffers_active = { bg = "#a89984", fg = "#3c3836" } + 3: lualine_a_buffers_active = { bg = "#a89984", bold = true, fg = "#282828" } + 4: lualine_transitional_lualine_a_buffers_active_to_lualine_a_buffers_inactive = { bg = "#3c3836", fg = "#a89984" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: a.txt } + {2:} + {3: b.txt } + {4:} + {1: [No Name] } + {5: }| + ]===]) + + vim.cmd('tabprev') + tabline:expect([===[ + highlights = { + 1: lualine_a_buffers_active = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_buffers_active_to_lualine_a_buffers_inactive = { bg = "#3c3836", fg = "#a89984" } + 3: lualine_a_buffers_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 4: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: a.txt } + {2:} + {3: b.txt } + {3: [No Name] } + {4: }| + ]===]) + + vim.cmd('tabprev') + tabline:expect([===[ + highlights = { + 1: lualine_a_buffers_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 2: lualine_transitional_lualine_a_buffers_inactive_to_lualine_a_buffers_active = { bg = "#a89984", fg = "#3c3836" } + 3: lualine_a_buffers_active = { bg = "#a89984", bold = true, fg = "#282828" } + 4: lualine_transitional_lualine_a_buffers_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: a.txt } + {1: b.txt } + {2:} + {3: [No Name] } + {4:} + {5: }| + ]===]) + end) + + it('mode option can change layout', function() + local conf = vim.deepcopy(tab_conf) + conf.tabline.lualine_a = { { 'tabs', max_length = 1e3, mode = 0, icons_enabled = false } } + vim.cmd('tabe ' .. 'a.txt') + vim.cmd('tabe ' .. 'b.txt') + require('lualine').setup(conf) + require('lualine').statusline() + tabline:expect([===[ + highlights = { + 1: lualine_a_tabs_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 2: lualine_transitional_lualine_a_tabs_inactive_to_lualine_a_tabs_active = { bg = "#a89984", fg = "#3c3836" } + 3: lualine_a_tabs_active = { bg = "#a89984", bold = true, fg = "#282828" } + 4: lualine_transitional_lualine_a_tabs_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + {MATCH:|{1: %d+ }} + {MATCH:{1: %d+ }} + {2:} + {MATCH:{3: %d+ }} + {4:} + {MATCH:{5:%s+}|} + ]===]) + + conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, mode = 1, icons_enabled = false } } + require('lualine').setup(conf) + require('lualine').statusline() + tabline:expect([===[ + highlights = { + 1: lualine_a_buffers_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 2: lualine_transitional_lualine_a_buffers_inactive_to_lualine_a_buffers_active = { bg = "#a89984", fg = "#3c3836" } + 3: lualine_a_buffers_active = { bg = "#a89984", bold = true, fg = "#282828" } + 4: lualine_transitional_lualine_a_buffers_active_to_lualine_a_buffers_inactive = { bg = "#3c3836", fg = "#a89984" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + {MATCH:|{1: %d+ }} + {2:} + {MATCH:{3: %d+ }} + {4:} + {MATCH:{1: %d+ }} + {MATCH:{5:%s+}|} + ]===]) + + conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, mode = 2, icons_enabled = false } } + require('lualine').setup(conf) + require('lualine').statusline() + tabline:expect([===[ + highlights = { + 1: lualine_a_buffers_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 2: lualine_transitional_lualine_a_buffers_inactive_to_lualine_a_buffers_active = { bg = "#a89984", fg = "#3c3836" } + 3: lualine_a_buffers_active = { bg = "#a89984", bold = true, fg = "#282828" } + 4: lualine_transitional_lualine_a_buffers_active_to_lualine_a_buffers_inactive = { bg = "#3c3836", fg = "#a89984" } + 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + {MATCH:|{1: %d+ a.txt }} + {2:} + {MATCH:{3: %d+ b.txt }} + {4:} + {MATCH:{1: %d+ %[No Name%] }} + {MATCH:{5:%s+}|} + ]===]) + end) + + it('can show modified status', function() + local conf = vim.deepcopy(tab_conf) + conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, show_modified_status = true, icons_enabled = false } } + require('lualine').setup(conf) + require('lualine').statusline() + tabline:expect([===[ + highlights = { + 1: lualine_a_buffers_active = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_buffers_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: [No Name] } + {2:} + {3: }| + ]===]) + + vim.bo.modified = true + tabline:expect([===[ + highlights = { + 1: lualine_a_buffers_active = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_buffers_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: [No Name] + } + {2:} + {3: }| + ]===]) + vim.bo.modified = false + end) + + it('can show relative path', function() + local conf = vim.deepcopy(tab_conf) + conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, show_filename_only = false, icons_enabled = false } } + require('lualine').setup(conf) + require('lualine').statusline() + local path = 'aaaaaa/bbbbb/cccccc/ddddd/eeeee/ffff/gggg' + vim.fn.mkdir(path, 'p') + vim.cmd('e ' .. path .. '/asdf.txt') + tabline:expect([===[ + highlights = { + 1: lualine_a_buffers_active = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_buffers_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1: a/b/c/d/e/f/g/asdf.txt } + {2:} + {3: }| + ]===]) + vim.fn.delete(path:match('(%w+)/.*'), 'rf') + end) + + it('can show ellipsis when max_width is crossed', function() + local conf = vim.deepcopy(tab_conf) + conf.tabline.lualine_a = { { 'buffers', max_length = 1 } } + vim.cmd('tabe a.txt') + vim.cmd('tabe b.txt') + vim.cmd('tabprev') + require('lualine').setup(conf) + require('lualine').statusline() + tabline:expect([===[ + highlights = { + 1: lualine_a_buffers_active = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_buffers_active_to_lualine_a_buffers_inactive = { bg = "#3c3836", fg = "#a89984" } + 3: lualine_a_buffers_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } + 4: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1:  a.txt } + {2:} + {3: ... } + {4: }| + ]===]) + end) + + it('can show filetype icons', function() + local conf = vim.deepcopy(tab_conf) + conf.tabline.lualine_a = { { 'buffers', max_length = 1e3, show_filename_only = false } } + require('lualine').setup(conf) + require('lualine').statusline() + vim.cmd('e t.lua') + tabline:expect([===[ + highlights = { + 1: lualine_a_buffers_active = { bg = "#a89984", bold = true, fg = "#282828" } + 2: lualine_transitional_lualine_a_buffers_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + 3: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } + } + |{1:  t.lua } + {2:} + {3: }| + ]===]) + end) + end) + end) end) diff --git a/lua/tests/statusline.lua b/lua/tests/statusline.lua new file mode 100644 index 0000000..9970f76 --- /dev/null +++ b/lua/tests/statusline.lua @@ -0,0 +1,316 @@ +-- Copyright (c) 2020-2021 shadmansaleh +-- MIT license, see LICENSE for more details. + +--- ## Testing module for lualines statusline +--- +--- ###Uses: +--- +--- Create a new instence with status width 120 & for active statusline +--- like following. +--- +--- ``lua +--- local statusline = require('tests.statusline').new(120, 'active') +--- ``` +--- +--- To create a new instence with status width 80 & for inactive statusline use following. +--- +--- ``lua +--- local statusline = require('tests.statusline').new(120, 'inactive') +--- ``` +--- +--- Now setup the state you want to test. +--- To test you'll call `expect` pmethod on statusline for example. +--- +--- To create a new instence with status width 80 & tabline +--- +--- ``lua +--- local statusline = require('tests.statusline').new(120, 'tabline') +--- ``` +--- +--- Now setup the state you want to test. +--- To test you'll call `expect` method on statusline for example. +--- +--- ``lua +--- statusline:expect([===[ +--- highlights = { +--- 1: lualine_c_inactive = { bg = "#3c3836", fg = "#a89984" } +--- } +--- |{1: [No Name] } +--- {1: } +--- {1: 0:1 }| +--- +---]===]) +--- ``` +--- +--- For more flexibility you can match a patten in expect block. +--- ``lua +--- statusline:expect([===[ +--- highlights = { +--- 1: lualine_a_tabs_inactive = { bg = "#3c3836", bold = true, fg = "#a89984" } +--- 2: lualine_transitional_lualine_a_tabs_inactive_to_lualine_a_tabs_active = { bg = "#a89984", fg = "#3c3836" } +--- 3: lualine_a_tabs_active = { bg = "#a89984", bold = true, fg = "#282828" } +--- 4: lualine_transitional_lualine_a_tabs_active_to_lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } +--- 5: lualine_c_normal = { bg = "#3c3836", fg = "#a89984" } +--- } +--- {MATCH:|{1: %d+ }} +--- {MATCH:{1: %d+ }} +--- {2:} +--- {MATCH:{3: %d+ }} +--- {4:} +--- {MATCH:{5:%s+}|} +--- +---]===]) +--- ``` +--- +--- An easy way to create an expect block is to call `snapshot` method +--- on statusline where you'll call expect and run the test. It will print +--- an expect block based on the state of statusline. You can copy it and +--- replace the snapshot call with the expect call. +--- +--- ``lua +--- statusline:snapshot() +--- ``` + +local ffi = require('ffi') +local helpers = require('tests.helpers') +local stub = require('luassert.stub') + +local M = {} + +ffi.cdef([[ +typedef unsigned char char_u; +typedef struct window_S win_T; +extern win_T *curwin; +typedef struct { + char_u *start; + int userhl; +} stl_hlrec_t; +typedef struct { +} StlClickDefinition; +typedef struct { + StlClickDefinition def; + const char *start; +} StlClickRecord; +int build_stl_str_hl( + win_T *wp, + char_u *out, + size_t outlen, + char_u *fmt, + int use_sandbox, + char_u fillchar, + int maxwidth, + stl_hlrec_t **hltab, + StlClickRecord **tabtab +); +]]) + +local function process_hlrec(hltab, stlbuf, eval_type) + local function default_hl() + if eval_type == 'tabline' then + return "TabLineFill" + elseif eval_type == 'inactive' then + return "StatusLineNC" + else + return "StatusLine" + end + end + local len = #ffi.string(stlbuf) + local hltab_data = hltab[0] + local result = {} + if hltab_data[0].start ~= stlbuf then + table.insert(result, { + group = default_hl(), + start = 0, + }) + end + + local n = 0 + while hltab_data[n].start ~= nil do + local group_name + if hltab_data[n].userhl == 0 then + group_name = default_hl() + elseif hltab_data[n].userhl < 0 then + group_name = vim.fn.synIDattr(-1 * hltab_data[n].userhl, 'name') + else + group_name = string.format('User%d', hltab_data[n].userhl) + end + + local hl_pos = { group = group_name } + + if n == 0 then + hl_pos.start = hltab_data[n].start - stlbuf + else + hl_pos.start = result[#result].start + result[#result].len + end + if hltab_data[n + 1].start ~= nil then + hl_pos.len = hltab_data[n + 1].start - hltab_data[n].start + else + hl_pos.len = (stlbuf + len) - hltab_data[n].start + end + table.insert(result, hl_pos) + n = n + 1 + end + return vim.tbl_filter(function(x) + return x.len ~= 0 + end, result) +end + +local function gen_stl(stl_fmt, width, eval_type) + local stlbuf = ffi.new('char_u [?]', width + 100) + local fmt = ffi.cast('char_u *', stl_fmt) + local fillchar = ffi.cast('char_u', 0x20) + local hltab = ffi.new('stl_hlrec_t *[1]', ffi.new('stl_hlrec_t *')) + ffi.C.build_stl_str_hl(ffi.C.curwin, stlbuf, width + 100, fmt, 0, fillchar, width, hltab, nil) + return { str = ffi.string(stlbuf), highlights = process_hlrec(hltab, stlbuf, eval_type) } +end + +local function eval_stl(stl_expr, width, eval_type) + local stl_buf, hl_list, stl_eval_res + if vim.fn.has('nvim-0.6') == 1 then + stl_eval_res = vim.api.nvim_eval_statusline( + stl_expr, + { maxwidth = width, highlights = true, fillchar = ' ', use_tabline = (eval_type == 'tabline')} + ) + else + stl_eval_res = gen_stl(stl_expr, width, eval_type) + end + stl_buf, hl_list = stl_eval_res.str, stl_eval_res.highlights + + local hl_map = {} + + local buf = { 'highlights = {' } + local hl_id = 1 + for _, hl in ipairs(hl_list) do + local hl_name = hl.group + if not hl_map[hl_name] then + hl_map[hl_name] = require('lualine.utils.utils').extract_highlight_colors(hl_name) or {} + table.insert( + buf, + string.format(' %4d: %s = %s', hl_id, hl_name, vim.inspect(hl_map[hl_name], { newline = ' ', indent = '' })) + ) + hl_map[hl_name].id = hl_id + hl_id = hl_id + 1 + end + end + table.insert(buf, '}') + + local stl = {} + for i = 1, #hl_list do + local start, finish = hl_list[i].start, hl_list[i + 1] and hl_list[i + 1].start or #stl_buf + if start ~= finish then + table.insert( + stl, + string.format('{%d:%s}', hl_map[hl_list[i].group].id, vim.fn.strpart(stl_buf, start, finish - start)) + ) + end + end + table.insert(buf, '|' .. table.concat(stl, '\n') .. '|') + table.insert(buf, '') + return table.concat(buf, '\n') +end + +function M:expect_expr(expect, expr) + expect = helpers.dedent(expect) + local actual = eval_stl(expr, self.width, self.type) + local matched = true + local errmsg = {} + if expect ~= actual then + expect = vim.split(expect, '\n') + actual = vim.split(actual, '\n') + if expect[#expect] == '' then + expect[#expect] = nil + end + if actual[#actual] == '' then + actual[#actual] = nil + end + for i = 1, math.max(#expect, #actual) do + if expect[i] and actual[i] then + local match_pat = expect[i]:match('{MATCH:(.*)}') + if expect[i] == actual[i] or (match_pat and actual[i]:match(match_pat)) then + expect[i] = string.rep(' ', 2) .. expect[i] + actual[i] = string.rep(' ', 2) .. actual[i] + goto loop_end + end + end + matched = false + if expect[i] then + expect[i] = '*' .. string.rep(' ', 1) .. expect[i] + end + if actual[i] then + actual[i] = '*' .. string.rep(' ', 1) .. actual[i] + end + ::loop_end:: + end + end + if not matched then + table.insert(errmsg, 'Unexpected statusline') + table.insert(errmsg, 'Expected:') + table.insert(errmsg, table.concat(expect, '\n') .. '\n') + table.insert(errmsg, 'Actual:') + table.insert(errmsg, table.concat(actual, '\n')) + end + assert(matched, table.concat(errmsg, '\n')) +end + +function M:snapshot_expr(expr) + local type_map = { + active = 'statusline', + inactive = 'inactive_statusline', + tabline = 'tabline', + } + print((type_map[self.type] or 'statusline') .. ':expect([===[') + print(eval_stl(expr, self.width, self.type) .. ']===])') +end + +function M:snapshot() + local utils = require('lualine.utils.utils') + stub(utils, 'is_focused') + utils.is_focused.returns(self.type ~= 'inactive') + local expr + if self.type == 'inactive' then + expr = require('lualine').statusline(false) + elseif self.type == 'tabline' then + expr = require('lualine').tabline() + else + expr = require('lualine').statusline(true) + end + self:snapshot_expr(expr) + utils.is_focused:revert() +end + +function M:expect(result) + local utils = require('lualine.utils.utils') + stub(utils, 'is_focused') + utils.is_focused.returns(self.type ~= 'inactive') + local expr + if self.type == 'inactive' then + expr = require('lualine').statusline(false) + elseif self.type == 'tabline' then + expr = require('lualine').tabline() + else + expr = require('lualine').statusline(true) + end + self:expect_expr(result, expr) + utils.is_focused:revert() +end + +function M.new(_, width, eval_type) + if type(_) ~= 'table' then + eval_type = width + width = _ + end + local self = {} + self.width = width or 120 + self.type = eval_type + if self.type == nil then + self.type = 'active' + end + return setmetatable(self, { + __index = M, + __call = function(_, ...) + M.new(...) + end, + }) +end + +return M.new()