151 lines
4.4 KiB
Lua
151 lines
4.4 KiB
Lua
local M = {}
|
|
|
|
function M.safe_require(name)
|
|
local ok, mod = pcall(require, name)
|
|
if ok then return mod end
|
|
return nil
|
|
end
|
|
|
|
-- Number of parent directories to show in full in the tabline
|
|
-- The rest will be shortened according to tabline_shorten_length
|
|
-- Example: with full_parents = 1, /path/to/my/project/src/file.txt becomes pat/to/my/project/src/file.txt
|
|
-- Example: with full_parents = 2, it becomes pat/to/my/project/src/file.txt
|
|
M.tabline_full_parents = 1
|
|
|
|
-- Number of characters to show for shortened directory names in the tabline
|
|
-- Example: with shorten_length = 3, /path/to/my becomes pat/to/my
|
|
-- Example: with shorten_length = 1, /path/to/my becomes p/t/m
|
|
M.tabline_shorten_length = 3
|
|
|
|
-- Get all modified, deleted, and untracked Git files with status
|
|
-- Returns a list suitable for setqflist() or nil on error
|
|
function M.git_changed_files()
|
|
-- Use git status --porcelain to get all changes with status indicators
|
|
-- Format: "XY filename" where X=index status, Y=worktree status
|
|
-- Status codes: M=modified, D=deleted, A=added, ??=untracked, etc.
|
|
local handle = io.popen('git status --porcelain 2>/dev/null')
|
|
if not handle then
|
|
vim.notify('Failed to run git status', vim.log.levels.ERROR)
|
|
return nil
|
|
end
|
|
|
|
local result = handle:read('*a')
|
|
handle:close()
|
|
|
|
if result == '' then
|
|
vim.notify('No git changes found', vim.log.levels.INFO)
|
|
return nil
|
|
end
|
|
|
|
local qf_list = {}
|
|
local status_map = {
|
|
['M'] = 'Modified',
|
|
['A'] = 'Added',
|
|
['D'] = 'Deleted',
|
|
['R'] = 'Renamed',
|
|
['C'] = 'Copied',
|
|
['U'] = 'Unmerged',
|
|
['?'] = 'Untracked',
|
|
}
|
|
|
|
for line in result:gmatch('[^\n]+') do
|
|
-- Parse porcelain format: "XY filename" or "XY original -> renamed"
|
|
local index_status = line:sub(1, 1)
|
|
local work_status = line:sub(2, 2)
|
|
local filename = line:sub(4) -- Skip "XY " prefix
|
|
|
|
-- Determine status text (worktree takes precedence over index)
|
|
local status_code = work_status ~= ' ' and work_status or index_status
|
|
local status_text = status_map[status_code] or 'Changed'
|
|
|
|
table.insert(qf_list, {
|
|
filename = filename,
|
|
lnum = 1,
|
|
text = status_text,
|
|
})
|
|
end
|
|
|
|
return qf_list
|
|
end
|
|
|
|
-- Custom tabline function
|
|
-- Shows configurable number of full parent directories, shortens the rest
|
|
function M.custom_tabline()
|
|
local tabline = ''
|
|
local num_tabs = vim.fn.tabpagenr('$')
|
|
|
|
for i = 1, num_tabs do
|
|
local buflist = vim.fn.tabpagebuflist(i)
|
|
local winnr = vim.fn.tabpagewinnr(i)
|
|
local bufnr = buflist[winnr]
|
|
local bufname = vim.fn.bufname(bufnr)
|
|
local bufmodified = vim.fn.getbufvar(bufnr, "&modified")
|
|
|
|
-- Highlight for the tab
|
|
if i == vim.fn.tabpagenr() then
|
|
tabline = tabline .. '%#TabLineSel#'
|
|
else
|
|
tabline = tabline .. '%#TabLine#'
|
|
end
|
|
|
|
-- Tab number
|
|
tabline = tabline .. ' ' .. i .. ' '
|
|
|
|
-- Format the filename with smart path shortening
|
|
local filename
|
|
if bufname == '' then
|
|
filename = '[No Name]'
|
|
else
|
|
-- Get the full path relative to cwd if possible
|
|
local path = vim.fn.fnamemodify(bufname, ':~:.')
|
|
|
|
-- Split path into components
|
|
local parts = vim.split(path, '/', { plain = true })
|
|
|
|
if #parts > M.tabline_full_parents + 1 then
|
|
-- We have enough parts to do smart shortening
|
|
local result = {}
|
|
|
|
-- Shorten the leading directories (all but the last full_parents + filename)
|
|
local num_to_shorten = #parts - M.tabline_full_parents - 1
|
|
for j = 1, num_to_shorten do
|
|
table.insert(result, parts[j]:sub(1, M.tabline_shorten_length))
|
|
end
|
|
|
|
-- Add the full parent directories
|
|
for j = num_to_shorten + 1, #parts - 1 do
|
|
table.insert(result, parts[j])
|
|
end
|
|
|
|
-- Add the filename
|
|
table.insert(result, parts[#parts])
|
|
|
|
filename = table.concat(result, '/')
|
|
else
|
|
-- Path is short enough, just use it as-is
|
|
filename = path
|
|
end
|
|
end
|
|
|
|
-- Add modified flag
|
|
if bufmodified == 1 then
|
|
filename = filename .. ' [+]'
|
|
end
|
|
|
|
tabline = tabline .. filename .. ' '
|
|
end
|
|
|
|
-- Fill the rest with TabLineFill
|
|
tabline = tabline .. '%#TabLineFill#%T'
|
|
|
|
-- Right-align: show tab page count if more than one tab
|
|
if num_tabs > 1 then
|
|
tabline = tabline .. '%=%#TabLine# ' .. num_tabs .. ' tabs '
|
|
end
|
|
|
|
return tabline
|
|
end
|
|
|
|
return M
|
|
|