feat(picker.util): smart path truncate. Defaults to 40. Closes #708

This commit is contained in:
Folke Lemaitre 2025-01-23 12:00:02 +01:00
parent c25bf490b0
commit bab8243395
No known key found for this signature in database
GPG key ID: 41F8B1FBACAE2040
4 changed files with 49 additions and 1 deletions

View file

@ -25,6 +25,7 @@ end
--- Gets the git root for a buffer or path. --- Gets the git root for a buffer or path.
--- Defaults to the current buffer. --- Defaults to the current buffer.
---@param path? number|string buffer or path ---@param path? number|string buffer or path
---@return string?
function M.get_root(path) function M.get_root(path)
path = path or 0 path = path or 0
path = type(path) == "number" and vim.api.nvim_buf_get_name(path) or path --[[@as string]] path = type(path) == "number" and vim.api.nvim_buf_get_name(path) or path --[[@as string]]

View file

@ -133,6 +133,7 @@ local defaults = {
}, },
file = { file = {
filename_first = false, -- display filename before the file path filename_first = false, -- display filename before the file path
truncate = 40, -- truncate the file path to (roughly) this length
}, },
selected = { selected = {
show_always = false, -- only show the selected column when there are multiple selections show_always = false, -- only show the selected column when there are multiple selections

View file

@ -26,7 +26,7 @@ function M.filename(item, picker)
return ret return ret
end end
local path = Snacks.picker.util.path(item) or item.file local path = Snacks.picker.util.path(item) or item.file
path = vim.fn.fnamemodify(path, ":~:."):gsub("\\", "/") path = Snacks.picker.util.truncpath(path, picker.opts.formatters.file.truncate or 40, { cwd = picker:cwd() })
local name, cat = path, "file" local name, cat = path, "file"
if item.buf and vim.api.nvim_buf_is_loaded(item.buf) then if item.buf and vim.api.nvim_buf_is_loaded(item.buf) then
name = vim.bo[item.buf].filetype name = vim.bo[item.buf].filetype

View file

@ -13,6 +13,52 @@ function M.path(item)
return item._path return item._path
end end
---@param path string
---@param len? number
---@param opts? {cwd?: string}
function M.truncpath(path, len, opts)
local cwd = vim.fs.normalize(opts and opts.cwd or vim.fn.getcwd(), { _fast = true, expand_env = false })
local home = vim.fs.normalize("~")
path = vim.fs.normalize(path, { _fast = true, expand_env = false })
if path:find(cwd, 1, true) == 1 then
path = path:sub(#cwd + 2)
else
local root = Snacks.git.get_root(path)
if root and root ~= "" and path:find(root, 1, true) == 1 then
local tail = vim.fn.fnamemodify(root, ":t")
path = "" .. tail .. "/" .. path:sub(#root + 2)
elseif path:find(home, 1, true) == 1 then
path = "~" .. path:sub(#home + 1)
end
end
if vim.api.nvim_strwidth(path) <= len then
return path
end
local parts = vim.split(path, "/")
if #parts < 2 then
return path
end
local ret = table.remove(parts)
local first = table.remove(parts, 1)
if first == "~" and #parts > 0 then
first = "~/" .. table.remove(parts, 1)
end
local width = vim.api.nvim_strwidth(ret) + vim.api.nvim_strwidth(first) + 3
while width < len and #parts > 0 do
local part = table.remove(parts) .. "/"
local w = vim.api.nvim_strwidth(part)
if width + w > len then
break
end
ret = part .. ret
width = width + w
end
return first .. "/…/" .. ret
end
---@param cmd string|string[] ---@param cmd string|string[]
---@param cb fun(output: string[], code: number) ---@param cb fun(output: string[], code: number)
---@param opts? {env?: table<string, string>, cwd?: string} ---@param opts? {env?: table<string, string>, cwd?: string}