You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

530 lines
11 KiB
Lua

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

local M = {}
local C = require("catppuccin.palettes").get_palette()
local lsp = require("feline.providers.lsp")
local navic = require("nvim-navic")
local assets = {
left_separator = "",
right_separator = "",
mode_icon = "",
dir = "",
file = "",
lsp = {
server = "",
error = "",
warning = "",
info = "",
hint = "",
},
git = {
branch = "",
added = "",
changed = "",
removed = "",
},
}
local sett = {
text = C.surface0,
bkg = C.surface0,
diffs = C.mauve,
extras = C.overlay1,
curr_file = C.maroon,
curr_dir = C.flamingo,
show_modified = false,
}
if require("catppuccin").options.transparent_background then
sett.bkg = "NONE"
end
local mode_colors = {
["n"] = { "NORMAL", C.lavender },
["no"] = { "N-PENDING", C.lavender },
["i"] = { "INSERT", C.green },
["ic"] = { "INSERT", C.green },
["t"] = { "TERMINAL", C.green },
["v"] = { "VISUAL", C.flamingo },
["V"] = { "V-LINE", C.flamingo },
[""] = { "V-BLOCK", C.flamingo },
["R"] = { "REPLACE", C.maroon },
["Rv"] = { "V-REPLACE", C.maroon },
["s"] = { "SELECT", C.maroon },
["S"] = { "S-LINE", C.maroon },
[""] = { "S-BLOCK", C.maroon },
["c"] = { "COMMAND", C.peach },
["cv"] = { "COMMAND", C.peach },
["ce"] = { "COMMAND", C.peach },
["r"] = { "PROMPT", C.teal },
["rm"] = { "MORE", C.teal },
["r?"] = { "CONFIRM", C.mauve },
["!"] = { "SHELL", C.green },
}
function M.setup(opts)
if opts then
opts.assets = opts.assets or {}
opts.sett = opts.sett or {}
opts.mode_colors = opts.mode_colors or {}
else
opts = {}
end
assets = vim.tbl_deep_extend("force", assets, opts.assets)
sett = vim.tbl_deep_extend("force", sett, opts.sett)
mode_colors = vim.tbl_deep_extend("force", mode_colors, opts.mode_colors)
end
function M.get()
local shortline = false
local components = {
active = { {}, {}, {} }, -- left, center, right
inactive = { {} },
}
local function is_enabled(min_width)
if shortline then
return true
end
return vim.api.nvim_win_get_width(0) > min_width
end
-- global components
local invi_sep = {
str = " ",
hl = {
fg = sett.bkg,
bg = sett.bkg,
},
}
-- helpers
local function has_git_head()
return vim.b.gitsigns_head ~= nil
end
local function any_git_changes()
local gst = vim.b.gitsigns_status_dict -- git stats
if gst then
if
gst["added"] and gst["added"] > 0
or gst["removed"] and gst["removed"] > 0
or gst["changed"] and gst["changed"] > 0
then
return true
end
end
return false
end
-- #################### STATUSLINE ->
-- ######## Left
-- Current vi mode ------>
local vi_mode_hl = function()
return {
fg = sett.text,
bg = mode_colors[vim.fn.mode()][2],
style = "bold",
}
end
components.active[1][1] = {
provider = " " .. assets.mode_icon .. " ",
hl = function()
return {
fg = sett.text,
bg = mode_colors[vim.fn.mode()][2],
}
end,
}
-- there is a dilema: we need to hide Diffs if ther is no git info. We can do that, but this will
-- leave the right_separator colored with purple, and since we can't change the color conditonally
-- then the solution is to create two right_separators: one with a mauve sett.bkg and the other one normal
-- sett.bkg; both have the same fg (vi mode). The mauve one appears if there is git info, else the one with
-- the normal sett.bkg appears. Fixed :)
components.active[1][2] = {
provider = assets.right_separator,
hl = function()
return {
fg = mode_colors[vim.fn.mode()][2],
bg = sett.bkg,
}
end,
enabled = function()
return not any_git_changes() and not has_git_head()
end,
}
components.active[1][3] = {
provider = assets.right_separator,
hl = function()
return {
fg = mode_colors[vim.fn.mode()][2],
bg = sett.diffs,
}
end,
enabled = function()
return any_git_changes()
end,
}
components.active[1][4] = {
provider = assets.right_separator,
hl = function()
return {
fg = mode_colors[vim.fn.mode()][2],
bg = C.maroon,
}
end,
enabled = function()
return not any_git_changes() and has_git_head()
end,
}
-- Current vi mode ------>
-- Diffs ------>
components.active[1][5] = {
provider = "git_diff_added",
hl = {
fg = sett.text,
bg = sett.diffs,
},
icon = " " .. assets.git.added .. " ",
}
components.active[1][6] = {
provider = "git_diff_changed",
hl = {
fg = sett.text,
bg = sett.diffs,
},
icon = " " .. assets.git.changed .. " ",
}
components.active[1][7] = {
provider = "git_diff_removed",
hl = {
fg = sett.text,
bg = sett.diffs,
},
icon = " " .. assets.git.removed .. " ",
}
components.active[1][8] = {
provider = assets.right_separator,
hl = {
fg = sett.diffs,
bg = C.maroon,
},
enabled = function()
return any_git_changes()
end,
}
-- Diffs ------>
-- Git Branch & Breadcrumbs ------>
components.active[1][9] = {
provider = " ",
hl = {
fg = C.maroon,
bg = C.maroon,
},
enabled = function()
return has_git_head()
end,
}
components.active[1][10] = {
provider = "git_branch",
enabled = is_enabled(70),
hl = {
fg = sett.text,
bg = C.maroon,
},
icon = assets.git.branch .. " ",
}
components.active[1][11] = {
provider = " ",
hl = {
fg = sett.bkg,
bg = C.maroon,
},
enabled = function()
return has_git_head()
end,
}
components.active[1][12] = {
provider = assets.right_separator,
hl = {
fg = C.maroon,
bg = sett.bkg,
},
enabled = function()
return has_git_head()
end,
}
components.active[1][13] = {
provider = function()
return " " .. navic.get_location()
end,
enabled = function()
return navic.is_available()
end,
hl = {
fg = sett.text,
bg = sett.bkg,
},
}
components.active[1][14] = {
provider = " ",
hl = {
fg = sett.bkg,
bg = sett.bkg,
},
enabled = function()
return not navic.is_available()
end,
}
-- Git Branch & Breadcrumbs ------>
-- ######## Left
-- ######## Center
function map(arr, func)
local new_arr = {}
for i, v in ipairs(arr) do
new_arr[i] = func(v)
end
return new_arr
end
-- Diagnostics ------>
-- workspace loader
components.active[2][1] = {
provider = function()
local Lsp = vim.lsp.util.get_progress_messages()[1]
if Lsp then
local msg = Lsp.message or ""
local percentage = Lsp.percentage
if not percentage then
return ""
end
local title = Lsp.title or ""
local spinners = {
"",
"",
"",
}
local success_icon = {
"",
"",
"",
}
local ms = vim.loop.hrtime() / 1000000
local frame = math.floor(ms / 120) % #spinners
if percentage >= 70 then
return string.format(" %%<%s %s %s (%s%%%%) ", success_icon[frame + 1], title, msg, percentage)
end
return string.format(" %%<%s %s %s (%s%%%%) ", spinners[frame + 1], title, msg, percentage)
end
return ""
end,
enabled = is_enabled(80),
hl = {
fg = C.rosewater,
bg = sett.bkg,
},
}
-- general diagnostics (errors, warnings. info and hints)
components.active[2][2] = {
provider = "diagnostic_errors",
enabled = function()
return lsp.diagnostics_exist(vim.diagnostic.severity.ERROR)
end,
hl = {
fg = C.red,
bg = sett.bkg,
},
icon = " " .. assets.lsp.error .. " ",
}
components.active[2][3] = {
provider = "diagnostic_warnings",
enabled = function()
return lsp.diagnostics_exist(vim.diagnostic.severity.WARN)
end,
hl = {
fg = C.yellow,
bg = sett.bkg,
},
icon = " " .. assets.lsp.warning .. " ",
}
components.active[2][4] = {
provider = "diagnostic_info",
enabled = function()
return lsp.diagnostics_exist(vim.diagnostic.severity.INFO)
end,
hl = {
fg = C.sky,
bg = sett.bkg,
},
icon = " " .. assets.lsp.info .. " ",
}
components.active[2][5] = {
provider = "diagnostic_hints",
enabled = function()
return lsp.diagnostics_exist(vim.diagnostic.severity.HINT)
end,
hl = {
fg = C.rosewater,
bg = sett.bkg,
},
icon = " " .. assets.lsp.hint .. " ",
}
-- Diagnostics ------>
-- ######## Center
-- ######## Right
components.active[3][1] = {
provider = function()
local current_line = vim.fn.line(".")
local total_line = vim.fn.line("$")
if current_line == 1 then
return "Top"
elseif current_line == vim.fn.line("$") then
return "Bot"
end
local result, _ = math.modf((current_line / total_line) * 100)
return result .. "%%"
end,
-- enabled = shortline or function(winid)
-- return vim.api.nvim_win_get_width(winid) > 90
-- end,
hl = {
fg = sett.extras,
bg = sett.bkg,
},
right_sep = invi_sep,
}
-- position
components.active[3][2] = {
provider = "position",
-- enabled = shortline or function(winid)
-- return vim.api.nvim_win_get_width(winid) > 90
-- end,
hl = {
fg = sett.extras,
bg = sett.bkg,
},
right_sep = invi_sep,
}
-- macro
components.active[3][3] = {
provider = "macro",
enabled = function()
return vim.api.nvim_get_option("cmdheight") == 0
end,
hl = {
fg = sett.extras,
bg = sett.bkg,
},
right_sep = invi_sep,
}
-- search count
components.active[3][4] = {
provider = "search_count",
enabled = function()
return vim.api.nvim_get_option("cmdheight") == 0
end,
hl = {
fg = sett.extras,
bg = sett.bkg,
},
right_sep = invi_sep,
}
components.active[3][5] = {
provider = function()
local filename = vim.fn.expand("%:t")
local extension = vim.fn.expand("%:e")
local present, icons = pcall(require, "nvim-web-devicons")
local icon = present and icons.get_icon(filename, extension) or assets.file
return (sett.show_modified and "%m" or "") .. " " .. icon .. " " .. filename .. " "
end,
enabled = is_enabled(70),
hl = {
fg = sett.text,
bg = sett.curr_file,
},
left_sep = {
str = assets.left_separator,
hl = {
fg = sett.curr_file,
bg = sett.bkg,
},
},
}
components.active[3][6] = {
provider = function()
local dir_name = vim.fn.fnamemodify(vim.fn.getcwd(), ":t")
return " " .. assets.dir .. " " .. dir_name .. " "
end,
enabled = is_enabled(80),
hl = {
fg = sett.text,
bg = sett.curr_dir,
},
left_sep = {
str = assets.left_separator,
hl = {
fg = sett.curr_dir,
bg = sett.curr_file,
},
},
}
-- ######## Right
-- Inanctive components
components.inactive[1][1] = {
provider = function()
return " " .. string.upper(vim.bo.ft) .. " "
end,
hl = {
fg = C.overlay2,
bg = C.mantle,
},
}
return components
end
return M