Sanchayan Maity
add2ceb869
Use it to show full path for file. This frees up space in status line when git branch names are long.
282 lines
7.2 KiB
Lua
282 lines
7.2 KiB
Lua
local fn = vim.fn
|
||
local api = vim.api
|
||
|
||
local gstatus = { ahead = 0, behind = 0 }
|
||
local update_gstatus = function()
|
||
local Job = require 'plenary.job'
|
||
Job:new({
|
||
command = 'git',
|
||
args = { 'rev-list', '--left-right', '--count', 'HEAD...@{upstream}' },
|
||
on_exit = function(exit_job, _)
|
||
local res = exit_job:result()[1]
|
||
if type(res) ~= 'string' then
|
||
gstatus = { ahead = 0, behind = 0 };
|
||
return
|
||
end
|
||
local ok, ahead, behind = pcall(string.match, res, "(%d+)%s*(%d+)")
|
||
if not ok then
|
||
ahead, behind = 0, 0
|
||
end
|
||
gstatus = { ahead = ahead, behind = behind }
|
||
end,
|
||
}):start()
|
||
end
|
||
|
||
if _G.Gstatus_timer == nil then
|
||
_G.Gstatus_timer = vim.loop.new_timer()
|
||
else
|
||
_G.Gstatus_timer:stop()
|
||
end
|
||
|
||
_G.Gstatus_timer:start(0, 2000, vim.schedule_wrap(update_gstatus))
|
||
|
||
local M = {}
|
||
|
||
local colors = {
|
||
line_bg = '#21242b',
|
||
bg = '#000000',
|
||
fg = '#dobfa1',
|
||
yellow = '#fabd2f',
|
||
cyan = '#008080',
|
||
darkblue = '#081633',
|
||
green = '#afd700',
|
||
orange = '#FF8800',
|
||
purple = '#5d4d7a',
|
||
magenta = '#c678dd',
|
||
blue = '#51afef',
|
||
red = '#ec5f67'
|
||
}
|
||
|
||
local function highlight(group, fg, bg)
|
||
api.nvim_set_hl(0, group, { fg = fg, bg = bg })
|
||
end
|
||
|
||
highlight("Window" , colors.red , colors.bg)
|
||
highlight("Mode" , colors.green , colors.bg)
|
||
highlight("Filename" , colors.blue , colors.bg)
|
||
highlight("Fileformat" , colors.purple , colors.bg)
|
||
|
||
highlight("GitBranch" , colors.orange , colors.bg)
|
||
highlight("GitStatus" , colors.magenta, colors.bg)
|
||
highlight("DiffAdded" , colors.green , colors.bg)
|
||
highlight("DiffChanged" , colors.orange , colors.bg)
|
||
highlight("DiffRemoved" , colors.red , colors.bg)
|
||
|
||
highlight("DiagnosticsE", colors.red , colors.bg)
|
||
highlight("DiagnosticsW", colors.yellow , colors.bg)
|
||
highlight("DiagnosticsI", colors.cyan , colors.bg)
|
||
highlight("DiagnosticsH", colors.orange , colors.bg)
|
||
|
||
highlight("Location" , colors.yellow , colors.bg)
|
||
highlight("Progress" , colors.magenta, colors.bg)
|
||
highlight("WinbarFile" , colors.magenta, colors.bg)
|
||
|
||
M.trunc_width = setmetatable({
|
||
git_status = 80,
|
||
filename = 140,
|
||
}, {
|
||
__index = function()
|
||
return 80
|
||
end,
|
||
})
|
||
|
||
M.is_truncated = function(_, width)
|
||
return api.nvim_win_get_width(0) < width
|
||
end
|
||
|
||
M.get_window_number = function()
|
||
return string.format(" %s%d", "%#Window#", api.nvim_win_get_number(0))
|
||
end
|
||
|
||
M.modes = setmetatable({
|
||
["n" ] = "N" ,
|
||
["no"] = "N·P",
|
||
["v" ] = "V" ,
|
||
["V" ] = "V·L",
|
||
[""] = "V·B", -- this is not ^V, but it's , they're different
|
||
["s" ] = "S" ,
|
||
["S" ] = "S·L",
|
||
[""] = "S·B", -- same with this one, it's not ^S but it's
|
||
["i" ] = "I" ,
|
||
["ic"] = "I" ,
|
||
["R" ] = "R" ,
|
||
["Rv"] = "V·R",
|
||
["c" ] = "C" ,
|
||
["cv"] = "V·E",
|
||
["ce"] = "E" ,
|
||
["r" ] = "P" ,
|
||
["rm"] = "RM" ,
|
||
["r?"] = "C" ,
|
||
["!" ] = "S" ,
|
||
["t" ] = "T" ,
|
||
}, {
|
||
__index = function()
|
||
return "U"
|
||
end,
|
||
})
|
||
|
||
M.get_current_mode = function(self)
|
||
local current_mode = api.nvim_get_mode().mode
|
||
return string.format(" %s%s", "%#Mode#", self.modes[current_mode])
|
||
end
|
||
|
||
M.get_git_branch = function(self)
|
||
if self:is_truncated(self.trunc_width.git_status) then
|
||
return ""
|
||
end
|
||
|
||
return string.format(" %s %s", "%#GitBranch#", fn.FugitiveHead())
|
||
end
|
||
|
||
M.get_git_status = function(self)
|
||
local signs = vim.b.gitsigns_status_dict
|
||
or { head = "", added = 0, changed = 0, removed = 0 }
|
||
local is_head_empty = signs.head ~= ""
|
||
|
||
return is_head_empty
|
||
and string.format(
|
||
" %s+%s %s~%s %s-%s",
|
||
"%#DiffAdded#",
|
||
signs.added or 0,
|
||
"%#DiffChanged#",
|
||
signs.changed or 0,
|
||
"%#DiffRemoved#",
|
||
signs.removed or 0
|
||
)
|
||
or ""
|
||
end
|
||
|
||
M.get_filename = function()
|
||
local filetype = vim.bo.filetype
|
||
local special_ft = { 'diff', 'fugitive', 'git', 'qf' }
|
||
for _, v in pairs(special_ft) do
|
||
if v == filetype then
|
||
return string.format(" %s%s", "%#Filename#", filetype)
|
||
end
|
||
end
|
||
|
||
return string.format(" %s%s", "%#Filename#", '%t%m%r')
|
||
end
|
||
|
||
M.get_fileformat = function()
|
||
return string.format("%s%s", "%#Fileformat#", vim.o.fileformat):lower()
|
||
end
|
||
|
||
M.diagnostic_status = function()
|
||
local diagnostic = ''
|
||
|
||
local num_errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR })
|
||
if num_errors > 0 then
|
||
diagnostic = string.format("%s%s%d", diagnostic, ' %#DiagnosticsE#E:', num_errors)
|
||
end
|
||
|
||
local num_warnings = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN })
|
||
if num_warnings > 0 then
|
||
diagnostic = string.format("%s%s%d", diagnostic, ' %#DiagnosticsW#W:', num_warnings)
|
||
end
|
||
|
||
local num_infos = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.INFO })
|
||
if num_infos > 0 then
|
||
diagnostic = string.format("%s%s%d", diagnostic, ' %#DiagnosticsI#I:', num_infos)
|
||
end
|
||
|
||
local num_hints = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.HINT })
|
||
if num_hints > 0 then
|
||
diagnostic = string.format("%s%s%d", diagnostic, ' %#DiagnosticsH#H:', num_hints)
|
||
end
|
||
|
||
return diagnostic
|
||
end
|
||
|
||
M.get_line_col = function()
|
||
return string.format(" %s%s", "%#Location#", "%l:%c")
|
||
end
|
||
|
||
M.progress = function()
|
||
return string.format(" %s%s", "%#Progress#", "%3p%% ")
|
||
end
|
||
|
||
M.git_ahead_behind_status = function()
|
||
return
|
||
vim.b.gitsigns_status_dict
|
||
and
|
||
string.format(" %s%s%d%s%d", '%#GitStatus#', ' ', gstatus.behind, ' ', gstatus.ahead)
|
||
or ""
|
||
end
|
||
|
||
M.set_active = function(self)
|
||
return table.concat {
|
||
self:get_filename(),
|
||
self:get_git_status(),
|
||
self:git_ahead_behind_status(),
|
||
"%=",
|
||
self:diagnostic_status(),
|
||
self:get_line_col(),
|
||
self:progress(),
|
||
}
|
||
end
|
||
|
||
M.set_inactive = function(self)
|
||
return table.concat {
|
||
"%#Window#",
|
||
-- Putting this in a function like the others seems to not work. And takes
|
||
-- the window number of the active window. Same for filename.
|
||
" %{winnr()}",
|
||
self:get_git_branch(),
|
||
"%=",
|
||
self:get_fileformat(),
|
||
self:get_line_col(),
|
||
self:progress(),
|
||
}
|
||
end
|
||
|
||
_G.Statusline = setmetatable(M, {
|
||
__call = function(self, mode)
|
||
return self["set_" .. mode](self)
|
||
end,
|
||
})
|
||
|
||
local status_id = api.nvim_create_augroup("Statusline", {clear = true})
|
||
local hide_status_id = api.nvim_create_augroup("HideStatusline", {clear = true})
|
||
|
||
api.nvim_create_autocmd({"WinEnter", "BufEnter"}, {
|
||
group = status_id,
|
||
pattern = "*",
|
||
command = "setlocal statusline=%!v:lua.Statusline('active')"
|
||
})
|
||
api.nvim_create_autocmd({"WinLeave" , "BufLeave"}, {
|
||
group = status_id,
|
||
pattern = "*",
|
||
command = "setlocal statusline=%!v:lua.Statusline('inactive')"
|
||
})
|
||
api.nvim_create_autocmd({"BufWinEnter", "BufFilePost"}, {
|
||
group = status_id,
|
||
callback = function()
|
||
local winbar_filetype_exclude = {
|
||
"diff",
|
||
"fugitive",
|
||
"git",
|
||
"help",
|
||
"packer",
|
||
"qf"
|
||
}
|
||
|
||
if vim.tbl_contains(winbar_filetype_exclude, vim.bo.filetype) then
|
||
vim.opt_local.winbar = nil
|
||
return
|
||
end
|
||
|
||
vim.opt_local.winbar = string.format(" %s%s", "%#WinbarFile#", '%f%m%r')
|
||
end,
|
||
})
|
||
api.nvim_create_autocmd({"TermOpen", "TermEnter"}, {
|
||
group = hide_status_id,
|
||
pattern = "*",
|
||
command = "set laststatus=0 noshowmode noruler"
|
||
})
|
||
api.nvim_create_autocmd({"TermLeave"}, {
|
||
group = hide_status_id,
|
||
pattern = "*",
|
||
command = "set laststatus=2 showmode ruler"
|
||
})
|