Hoang Nguyen
0c9e4d20e0
Also: - remove `nvim-navic` from the plugin tree (covered by aerial.nvim now) - add more filetypes to filetype.lua - rework heirline's configuration structure to be cleaner - add some more LSP servers + remove glint
491 lines
14 KiB
Lua
491 lines
14 KiB
Lua
local M = {}
|
|
local conditions = require('heirline.conditions')
|
|
local utils = require('heirline.utils')
|
|
local misc_utils = require('user.util.misc')
|
|
local lsp_utils = require('user.util.lsp')
|
|
local vars = require('user.config.vars')
|
|
|
|
M.vi_mode = {
|
|
init = function(self)
|
|
self.mode = vim.fn.mode(1)
|
|
self.mode_color = self.mode_colors[self.mode:sub(1, 1)]
|
|
end,
|
|
static = {
|
|
mode_names = {
|
|
n = 'NORMAL',
|
|
no = 'OP',
|
|
nov = 'OP(v)',
|
|
noV = 'OP(V)',
|
|
['no\22'] = 'OP(^V)',
|
|
niI = 'NORMAL(I)',
|
|
niR = 'NORMAL(R)',
|
|
niV = 'NORMAL(V)',
|
|
nt = 'NORMAL(T)',
|
|
ntT = 'NORMAL(T)',
|
|
v = 'VISUAL',
|
|
vs = 'VISUAL(s)',
|
|
V = 'V-LINE',
|
|
Vs = 'V-LINE(s)',
|
|
['\22'] = 'V-BLOCK',
|
|
['\22s'] = 'V-BLOCK(s)',
|
|
s = 'SELECT',
|
|
S = 'S-LINE',
|
|
['\19'] = 'S-BLOCK',
|
|
i = 'INSERT',
|
|
ic = 'INSERT(c)',
|
|
ix = 'INSERT(x)',
|
|
R = 'REPLACE',
|
|
Rc = 'REPLACE(c)',
|
|
Rx = 'REPLACE(x)',
|
|
Rv = 'REPLACE(v)',
|
|
Rvc = 'REPLACE(vc)',
|
|
Rvx = 'REPLACE(vx)',
|
|
c = 'COMMAND',
|
|
cv = 'EX',
|
|
r = 'ENTER',
|
|
rm = 'MORE',
|
|
['r?'] = 'CONFIRM',
|
|
['!'] = 'SHELL',
|
|
t = 'TERM',
|
|
},
|
|
mode_colors = {
|
|
n = 'green',
|
|
v = 'yellow',
|
|
V = 'yellow',
|
|
['\22'] = 'yellow',
|
|
s = 'orange',
|
|
S = 'orange',
|
|
['\19'] = 'yellow',
|
|
i = 'blue',
|
|
R = 'red',
|
|
c = 'purple',
|
|
r = 'cyan',
|
|
['!'] = 'fg',
|
|
t = 'fg',
|
|
},
|
|
},
|
|
provider = function(self)
|
|
return ' ' .. self.mode_names[self.mode] .. ' '
|
|
end,
|
|
hl = function(self)
|
|
return { fg = self.mode_color, bold = true }
|
|
end,
|
|
update = {
|
|
'ModeChanged',
|
|
pattern = '*:*',
|
|
callback = vim.schedule_wrap(function()
|
|
vim.cmd('redrawstatus')
|
|
end),
|
|
},
|
|
}
|
|
|
|
M.file_size = {
|
|
condition = misc_utils.buffer_not_empty,
|
|
provider = function()
|
|
local suffix = { 'b', 'k', 'M', 'G', 'T', 'P', 'E' }
|
|
local fsize = vim.fn.getfsize(vim.api.nvim_buf_get_name(0))
|
|
fsize = fsize < 0 and 0 or fsize
|
|
if fsize == 0 then
|
|
return ''
|
|
end
|
|
if fsize < 1024 then
|
|
return fsize .. suffix[1] .. ' '
|
|
end
|
|
local i = math.floor((math.log(fsize) / math.log(1024)))
|
|
return string.format('%.2g%s ', fsize / math.pow(1024, i), suffix[i + 1])
|
|
end,
|
|
hl = { fg = 'blue', bold = true },
|
|
}
|
|
|
|
M.file_format = {
|
|
condition = misc_utils.buffer_not_empty,
|
|
provider = function()
|
|
local os = vim.bo.fileformat:upper()
|
|
local icon = ''
|
|
if os == 'UNIX' then
|
|
icon = ' '
|
|
elseif os == 'MAC' then
|
|
icon = ' '
|
|
else
|
|
icon = ' '
|
|
end
|
|
return ' ' .. icon .. os
|
|
end,
|
|
hl = { fg = 'cyan' },
|
|
}
|
|
|
|
M.file_type = {
|
|
provider = function()
|
|
return ' ' .. string.upper(vim.bo.filetype)
|
|
end,
|
|
hl = { fg = 'blue', bold = true },
|
|
}
|
|
|
|
M.file_encoding = {
|
|
provider = function()
|
|
local enc = vim.bo.fenc ~= '' and vim.bo.fenc or vim.o.enc
|
|
return enc ~= 'utf-8' and (' ' .. enc:upper())
|
|
end,
|
|
hl = { fg = 'fg' },
|
|
}
|
|
|
|
M.file_info = {
|
|
init = function(self)
|
|
self.filename = vim.api.nvim_buf_get_name(0)
|
|
end,
|
|
{
|
|
init = function(self)
|
|
local extension = vim.fn.fnamemodify(self.filename, ':e')
|
|
self.icon, self.icon_color =
|
|
require('nvim-web-devicons').get_icon_color(self.filename, extension, { default = true })
|
|
end,
|
|
provider = function(self)
|
|
return self.icon and (self.icon .. ' ')
|
|
end,
|
|
hl = function(self)
|
|
return { fg = self.icon_color and self.icon_color or 'fg' }
|
|
end,
|
|
},
|
|
{
|
|
provider = function(self)
|
|
if self.filename == '' then
|
|
return '[No Name]'
|
|
end
|
|
return vim.fn.fnamemodify(self.filename, ':p:t')
|
|
end,
|
|
on_click = {
|
|
callback = function()
|
|
require('telescope.builtin').find_files()
|
|
end,
|
|
name = 'heirline_file_name',
|
|
},
|
|
hl = function()
|
|
if vim.bo.modified then
|
|
return { fg = 'cyan', bold = true }
|
|
end
|
|
return { fg = 'blue', bold = true }
|
|
end,
|
|
},
|
|
{
|
|
condition = function()
|
|
return vim.bo.modified
|
|
end,
|
|
provider = ' ',
|
|
hl = { fg = 'green' },
|
|
},
|
|
{
|
|
condition = function()
|
|
return not vim.bo.modifiable or vim.bo.readonly
|
|
end,
|
|
provider = ' ',
|
|
hl = { fg = 'red' },
|
|
},
|
|
{ provider = '%<' },
|
|
}
|
|
|
|
M.ruler = {
|
|
provider = ' %7(%l/%3L%):%2c %P',
|
|
hl = { fg = 'fg' },
|
|
}
|
|
|
|
M.lsp_servers = {
|
|
condition = conditions.lsp_attached,
|
|
update = { 'LspAttach', 'LspDetach' },
|
|
provider = function()
|
|
local clients = {}
|
|
for _, client in ipairs(lsp_utils.active_lsp_clients { bufnr = 0 }) do
|
|
table.insert(clients, client.name)
|
|
end
|
|
|
|
return ' [' .. table.concat(clients, ', ') .. ']'
|
|
end,
|
|
on_click = {
|
|
callback = function()
|
|
vim.defer_fn(function()
|
|
vim.cmd('LspInfo')
|
|
end, 100)
|
|
end,
|
|
name = 'heirline_lsp_servers',
|
|
},
|
|
hl = { fg = 'purple' },
|
|
}
|
|
|
|
M.linters_formatters = {
|
|
condition = function()
|
|
return misc_utils.loaded('conform.nvim') or misc_utils.loaded('nvim-lint')
|
|
end,
|
|
update = { 'BufReadPost', 'BufWritePost', 'InsertLeave' },
|
|
provider = function()
|
|
local ret = {}
|
|
|
|
if misc_utils.loaded('nvim-lint') then
|
|
vim.list_extend(ret, lsp_utils.active_linters(0))
|
|
end
|
|
|
|
if misc_utils.loaded('conform.nvim') then
|
|
for _, formatter in ipairs(require('conform').list_formatters()) do
|
|
if formatter and formatter.name and (not vim.tbl_contains(ret, formatter.name)) then
|
|
table.insert(ret, formatter.name)
|
|
end
|
|
end
|
|
end
|
|
|
|
return ' [' .. table.concat(ret, ', ') .. ']'
|
|
end,
|
|
hl = { fg = 'cyan' },
|
|
}
|
|
|
|
M.aerial = {
|
|
flexible = 3,
|
|
hl = 'Normal',
|
|
update = 'CursorMoved',
|
|
condition = function()
|
|
return conditions.lsp_attached or misc_utils.loaded('nvim-treesitter')
|
|
end,
|
|
static = {
|
|
encode_pos = function(line, col, winnr)
|
|
return bit.bor(bit.lshift(line, 16), bit.lshift(col, 6), winnr)
|
|
end,
|
|
decode_pos = function(c)
|
|
return bit.rshift(c, 16), bit.band(bit.rshift(c, 6), 1023), bit.band(c, 63)
|
|
end,
|
|
},
|
|
{
|
|
provider = function(self)
|
|
local data = require('aerial').get_location(true) or {}
|
|
local children = {}
|
|
|
|
-- create a child for each level
|
|
for i, d in ipairs(data) do
|
|
local hlgroup = string.format('Aerial%sIcon', d.kind)
|
|
local child = {
|
|
{
|
|
provider = string.format('%s', d.icon),
|
|
hl = vim.fn.hlexists(hlgroup) == 1 and hlgroup or nil,
|
|
},
|
|
{ provider = string.gsub(d.name, '%%', '%%%%'):gsub('%s*->%s*', '') },
|
|
on_click = {
|
|
minwid = self.encode_pos(d.lnum, d.col, self.winnr),
|
|
callback = function(_, minwid)
|
|
local lnum, col, winnr = self.decode_pos(minwid)
|
|
vim.api.nvim_win_set_cursor(vim.fn.win_getid(winnr), { lnum, col })
|
|
end,
|
|
name = 'heirline_aerial',
|
|
},
|
|
}
|
|
|
|
if #data >= 1 and i < #data then
|
|
table.insert(child, { provider = ' > ', hl = { fg = 'cyan' } })
|
|
end
|
|
|
|
table.insert(children, child)
|
|
end
|
|
|
|
-- instantiate the new child, overwriting the previous one
|
|
self[1] = self:new(children, 1)
|
|
end,
|
|
},
|
|
{ provider = '' },
|
|
}
|
|
|
|
local function overseer_tasks_for_status(status)
|
|
return {
|
|
condition = function(self)
|
|
return self.tasks[status]
|
|
end,
|
|
provider = function(self)
|
|
return string.format('%s%d', self.symbols[status], #self.tasks[status])
|
|
end,
|
|
hl = function(self)
|
|
return { fg = self.colors[status] }
|
|
end,
|
|
}
|
|
end
|
|
M.overseer = {
|
|
condition = function()
|
|
return misc_utils.loaded('overseer.nvim')
|
|
end,
|
|
init = function(self)
|
|
local tasks = require('overseer.task_list').list_tasks { unique = true }
|
|
self.tasks = require('overseer.util').tbl_group_by(tasks, 'status')
|
|
end,
|
|
static = {
|
|
symbols = {
|
|
CANCELED = ' ',
|
|
FAILURE = ' ',
|
|
RUNNING = ' ',
|
|
SUCCESS = ' ',
|
|
},
|
|
colors = {
|
|
CANCELED = 'highlight',
|
|
FAILURE = 'red',
|
|
RUNNING = 'yellow',
|
|
SUCCESS = 'green',
|
|
},
|
|
},
|
|
overseer_tasks_for_status('CANCELED'),
|
|
overseer_tasks_for_status('RUNNING'),
|
|
overseer_tasks_for_status('SUCCESS'),
|
|
overseer_tasks_for_status('FAILURE'),
|
|
on_click = {
|
|
callback = function()
|
|
require('neotest').run.run_last()
|
|
end,
|
|
name = 'heirline_overseer',
|
|
},
|
|
}
|
|
|
|
M.diagnostics = {
|
|
condition = conditions.has_diagnostics,
|
|
update = { 'DiagnosticChanged', 'BufEnter' },
|
|
init = function(self)
|
|
self.errors = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.ERROR })
|
|
self.warnings = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.WARN })
|
|
self.hints = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.HINT })
|
|
self.infos = #vim.diagnostic.get(0, { severity = vim.diagnostic.severity.INFO })
|
|
end,
|
|
on_click = {
|
|
callback = function()
|
|
require('telescope.builtin').diagnostics {
|
|
layout_strategy = 'center',
|
|
bufnr = 0,
|
|
}
|
|
end,
|
|
name = 'heirline_diagnostics',
|
|
},
|
|
{
|
|
condition = function(self)
|
|
return self.errors > 0
|
|
end,
|
|
provider = function(self)
|
|
return ' ' .. vars.icons.notify.error .. ' ' .. self.errors
|
|
end,
|
|
hl = { fg = utils.get_highlight('DiagnosticError').fg },
|
|
},
|
|
{
|
|
condition = function(self)
|
|
return self.warnings > 0
|
|
end,
|
|
provider = function(self)
|
|
return ' ' .. vars.icons.notify.warn .. ' ' .. self.warnings
|
|
end,
|
|
hl = { fg = utils.get_highlight('DiagnosticWarn').fg },
|
|
},
|
|
{
|
|
condition = function(self)
|
|
return self.hints > 0
|
|
end,
|
|
provider = function(self)
|
|
return ' ' .. vars.icons.notify.hint .. ' ' .. self.hints
|
|
end,
|
|
hl = { fg = utils.get_highlight('DiagnosticHint').fg },
|
|
},
|
|
{
|
|
condition = function(self)
|
|
return self.infos > 0
|
|
end,
|
|
provider = function(self)
|
|
return ' ' .. vars.icons.notify.info .. ' ' .. self.infos
|
|
end,
|
|
hl = { fg = utils.get_highlight('DiagnosticInfo').fg },
|
|
},
|
|
}
|
|
|
|
M.code_action = {
|
|
condition = conditions.lsp_attached,
|
|
update = { 'CursorMoved' },
|
|
provider = function()
|
|
if vim.b.has_code_action_text ~= nil then
|
|
return ' ' .. vim.b.has_code_action_text
|
|
end
|
|
end,
|
|
on_click = {
|
|
callback = function()
|
|
vim.defer_fn(function()
|
|
return vim.lsp.buf.code_action()
|
|
end, 100)
|
|
end,
|
|
name = 'heirline_code_action',
|
|
},
|
|
hl = { fg = 'cyan', bold = true },
|
|
}
|
|
|
|
M.git = {
|
|
condition = conditions.is_git_repo,
|
|
init = function(self)
|
|
self.status_dict = vim.b.gitsigns_status_dict
|
|
end,
|
|
{
|
|
provider = function(self)
|
|
return ' ' .. (self.status_dict.head == '' and 'main' or self.status_dict.head)
|
|
end,
|
|
on_click = {
|
|
name = 'heirline_git_branch',
|
|
callback = function()
|
|
require('telescope.builtin').git_branches()
|
|
end,
|
|
},
|
|
hl = { fg = 'green', bold = true },
|
|
},
|
|
{
|
|
condition = function(self)
|
|
return self.status_dict.added ~= 0 or self.status_dict.removed ~= 0 or self.status_dict.changed ~= 0
|
|
end,
|
|
{ provider = '(', hl = { fg = 'green', bold = true } },
|
|
{
|
|
provider = function(self)
|
|
local count = self.status_dict.added or 0
|
|
return count > 0 and ('+' .. count)
|
|
end,
|
|
hl = { fg = utils.get_highlight('DiffAdd').fg },
|
|
},
|
|
{
|
|
provider = function(self)
|
|
local count = self.status_dict.removed or 0
|
|
return count > 0 and ('-' .. count)
|
|
end,
|
|
hl = { fg = utils.get_highlight('DiffDelete').fg },
|
|
},
|
|
{
|
|
provider = function(self)
|
|
local count = self.status_dict.changed or 0
|
|
return count > 0 and ('~' .. count)
|
|
end,
|
|
hl = { fg = utils.get_highlight('DiffChange').fg },
|
|
},
|
|
{ provider = ')', hl = { fg = 'green', bold = true } },
|
|
},
|
|
}
|
|
|
|
M.dap = {
|
|
condition = function()
|
|
if not misc_utils.loaded('nvim-dap') then
|
|
return false
|
|
end
|
|
return require('dap').session() ~= nil
|
|
end,
|
|
provider = function()
|
|
return ' ' .. require('dap').status()
|
|
end,
|
|
on_click = {
|
|
callback = function()
|
|
require('dap').continue()
|
|
end,
|
|
name = 'heirline_dap',
|
|
},
|
|
hl = { fg = 'red', bold = true },
|
|
}
|
|
|
|
M.macro = {
|
|
condition = function()
|
|
return vim.fn.reg_recording() ~= '' and vim.o.cmdheight == 0
|
|
end,
|
|
provider = function()
|
|
return ' @ Recording ' .. vim.fn.reg_recording()
|
|
end,
|
|
update = { 'RecordingEnter', 'RecordingLeave' },
|
|
hl = { fg = 'green', bold = true },
|
|
}
|
|
|
|
return M
|