diff --git a/lua/lualine/components/filename.lua b/lua/lualine/components/filename.lua index b7f74f4..1d9232f 100644 --- a/lua/lualine/components/filename.lua +++ b/lua/lualine/components/filename.lua @@ -19,14 +19,6 @@ local default_options = { shorting_target = 40, } ----counts how many times pattern occur in base ( used for counting path-sep ) ----@param base string ----@param pattern string ----@return number -local function count(base, pattern) - return select(2, string.gsub(base, pattern, '')) -end - local function is_new_file() local filename = vim.fn.expand('%') return filename ~= '' and vim.bo.buftype == '' and vim.fn.filereadable(filename) == 0 @@ -35,10 +27,27 @@ end ---shortens path by turning apple/orange -> a/orange ---@param path string ---@param sep string path separator +---@param max_len integer maximum length of the full filename string ---@return string -local function shorten_path(path, sep) - -- ('([^/])[^/]+%/', '%1/', 1) - return path:gsub(string.format('([^%s])[^%s]+%%%s', sep, sep, sep), '%1' .. sep, 1) +local function shorten_path(path, sep, max_len) + local len = #path + if len <= max_len then + return path + end + + local segments = vim.split(path, sep) + for idx = 1, #segments - 1 do + if len <= max_len then + break + end + + local segment = segments[idx] + local shortened = segment:sub(1, vim.startswith(segment, '.') and 2 or 1) + segments[idx] = shortened + len = len - (#segment - #shortened) + end + + return table.concat(segments, sep) end M.init = function(self, options) @@ -73,11 +82,7 @@ M.update_status = function(self) local estimated_space_available = windwidth - self.options.shorting_target local path_separator = package.config:sub(1, 1) - for _ = 0, count(data, path_separator) do - if windwidth <= 84 or #data > estimated_space_available then - data = shorten_path(data, path_separator) - end - end + data = shorten_path(data, path_separator, estimated_space_available) end if self.options.file_status then diff --git a/tests/spec/component_spec.lua b/tests/spec/component_spec.lua index 4b7d1e9..f4f6634 100644 --- a/tests/spec/component_spec.lua +++ b/tests/spec/component_spec.lua @@ -455,19 +455,6 @@ describe('FileSize component', function() end) describe('Filename component', function() - local function shorten_path(path, target) - target = target and target or 40 - local sep = package.config:sub(1, 1) - local winwidth = vim.fn.winwidth(0) - local segments = select(2, string.gsub(path, sep, '')) - for _ = 0, segments do - if winwidth <= 84 or #path > winwidth - target then - path = path:gsub(string.format('([^%s])[^%s]+%%%s', sep, sep, sep), '%1' .. sep, 1) - end - end - return path - end - it('works', function() local opts = build_component_opts { component_separators = { left = '', right = '' }, @@ -506,7 +493,7 @@ describe('Filename component', function() path = 1, } vim.cmd(':e test-file.txt') - assert_component('filename', opts, shorten_path(vim.fn.expand('%:~:.'))) + assert_component('filename', opts, vim.fn.expand('%:~:.')) vim.cmd(':bdelete!') end) @@ -516,11 +503,75 @@ describe('Filename component', function() padding = 0, file_status = false, path = 2, + shorting_target = 0, } vim.cmd(':e test-file.txt') - assert_component('filename', opts, shorten_path(vim.fn.expand('%:p'))) + assert_component('filename', opts, vim.fn.expand('%:p')) vim.cmd(':bdelete!') end) + + it('shortens path', function() + stub(vim.fn, 'expand') + vim.fn.expand.on_call_with('%:p').returns('/home/foobar/test/test.lua') + stub(vim.fn, 'winwidth') + vim.fn.winwidth.on_call_with(0).returns(100) + + local opts = build_component_opts { + component_separators = { left = '', right = '' }, + padding = 0, + file_status = false, + path = 2, + shorting_target = 90, + } + vim.cmd(':e test-file.txt') + assert_component('filename', opts, '/h/f/t/test.lua') + + vim.cmd(':bdelete!') + vim.fn.winwidth:revert() + vim.fn.expand:revert() + end) + + it('shortens path with tilde', function() + stub(vim.fn, 'expand') + vim.fn.expand.on_call_with('%:p:~').returns('~/test/test.lua') + stub(vim.fn, 'winwidth') + vim.fn.winwidth.on_call_with(0).returns(100) + + local opts = build_component_opts { + component_separators = { left = '', right = '' }, + padding = 0, + file_status = false, + path = 3, + shorting_target = 90, + } + vim.cmd(':e test-file.txt') + assert_component('filename', opts, '~/t/test.lua') + + vim.cmd(':bdelete!') + vim.fn.winwidth:revert() + vim.fn.expand:revert() + end) + + it('shortens path with hidden directory', function() + stub(vim.fn, 'expand') + vim.fn.expand.on_call_with('%:p').returns('/home/foobar/.test/test.lua') + stub(vim.fn, 'winwidth') + vim.fn.winwidth.on_call_with(0).returns(100) + + local opts = build_component_opts { + component_separators = { left = '', right = '' }, + padding = 0, + file_status = false, + path = 2, + shorting_target = 90, + } + vim.cmd(':e test-file.txt') + assert_component('filename', opts, '/h/f/.t/test.lua') + + vim.cmd(':bdelete!') + vim.fn.winwidth:revert() + vim.fn.expand:revert() + end) end) describe('vim option & variable component', function()