neovim

mrgrouse's beloved, handmade neovim configuration
Log | Files | Refs | README

feline.lua (8789B)


      1 local lsp = require("feline.providers.lsp")
      2 local lsp_severity = vim.diagnostic.severity
      3 local b = vim.b
      4 
      5 local assets = {
      6 	left_semicircle = "",
      7 	right_semicircle = "",
      8 	right_semicircle_cut = "",
      9 	left_semicircle_cut = "",
     10 	vertical_bar_chubby = "█",
     11 	vertical_bar_medium = "┃",
     12 	vertical_bar_thin = "│",
     13 	left_arrow_thin = "",
     14 	right_arrow_thin = "",
     15 	left_arrow_filled = "",
     16 	right_arrow_filled = "",
     17 	slant_left = "",
     18 	slant_left_thin = "",
     19 	slant_right = "",
     20 	slant_right_thin = "",
     21 	slant_left_2 = "",
     22 	slant_left_2_thin = "",
     23 	slant_right_2 = "",
     24 	slant_right_2_thin = "",
     25 	chubby_dot = "●",
     26 	slim_dot = '•',
     27 }
     28 
     29 local colors = require('pywal.core').get_colors()
     30 
     31 -- settings
     32 local sett = {
     33 	bkg = colors.background,
     34 	diffs = colors.color1,
     35 	extras = colors.color5,
     36 	curr_file = colors.color4,
     37 	curr_dir = colors.color4,
     38 }
     39 
     40 local mode_colors = {
     41 	["n"] = { "NORMAL", colors.color1 },
     42 	["no"] = { "N-PENDING", colors.color1 },
     43 	["i"] = { "INSERT", colors.color1 },
     44 	["ic"] = { "INSERT", colors.color1 },
     45 	["t"] = { "TERMINAL", colors.color1 },
     46 	["v"] = { "VISUAL", colors.color3 },
     47 	["V"] = { "V-LINE", colors.color3 },
     48 	[""] = { "V-BLOCK", colors.color3 },
     49 	["R"] = { "REPLACE", colors.color4 },
     50 	["Rv"] = { "V-REPLACE", colors.color4 },
     51 	["s"] = { "SELECT", colors.color4 },
     52 	["S"] = { "S-LINE", colors.color4 },
     53 	[""] = { "S-BLOCK", colors.color4 },
     54 	["c"] = { "COMMAND", colors.color6 },
     55 	["cv"] = { "COMMAND", colors.color6 },
     56 	["ce"] = { "COMMAND", colors.color6 },
     57 	["r"] = { "PROMPT", colors.color7 },
     58 	["rm"] = { "MORE", colors.color7 },
     59 	["r?"] = { "CONFIRM", colors.color2 },
     60 	["!"] = { "SHELL", colors.color1 },
     61 }
     62 
     63 local shortline = false
     64 
     65 -- Initialize the components table
     66 local components = {
     67 	active = {},
     68 	inactive = {},
     69 }
     70 
     71 table.insert(components.active, {}) -- (1) left
     72 table.insert(components.active, {}) -- (2) center
     73 table.insert(components.active, {}) -- (3) right
     74 
     75 -- global components
     76 local invi_sep = {
     77 	str = " ",
     78 	hl = {
     79 		fg = sett.bkg,
     80 		bg = sett.bkg
     81 	},
     82 }
     83 
     84 -- helpers
     85 local function any_git_changes()
     86 	local gst = b.gitsigns_status_dict -- git stats
     87 	if gst then
     88 		if gst["added"] and gst["added"] > 0 or gst["removed"] and gst["removed"] > 0 or gst["changed"] and gst["changed"] > 0 then
     89 			return true
     90 		end
     91 	end
     92 	return false
     93 end
     94 
     95 
     96 -- #################### STATUSLINE ->
     97 
     98 
     99 -- ######## Left
    100 
    101 -- Current vi mode ------>
    102 local vi_mode_hl = function()
    103 	return {
    104 		fg = sett.bkg,
    105 		bg = mode_colors[vim.fn.mode()][2],
    106 		style = "bold"
    107 	}
    108 end
    109 
    110 components.active[1][1] = {
    111 	provider = assets.vertical_bar_chubby,
    112 	hl = function()
    113 		return {
    114 			fg = mode_colors[vim.fn.mode()][2],
    115 			bg = sett.bkg,
    116 		}
    117 	end,
    118 }
    119 
    120 components.active[1][2] = {
    121 	provider = "",
    122 	hl = function()
    123 		return {
    124 			fg = sett.bkg,
    125 			bg = mode_colors[vim.fn.mode()][2],
    126 		}
    127 	end,
    128 }
    129 
    130 components.active[1][3] = {
    131 	provider = function()
    132 		return " " .. mode_colors[vim.fn.mode()][1] .. " "
    133 	end,
    134 	hl = vi_mode_hl,
    135 }
    136 
    137 -- there is a dilema: we need to hide Diffs if ther is no git info. We can do that, but this will
    138 -- leave the right_semicircle colored with purple, and since we can't change the color conditonally
    139 -- then the solution is to create two right_semicircles: one with a color2 sett.bkg and the other one normal
    140 -- sett.bkg; both have the same fg (vi mode). The color2 one appears if there is git info, else the one with
    141 -- the normal sett.bkg appears. Fixed :)
    142 
    143 -- enable if git diffs are not available
    144 components.active[1][4] = {
    145 	provider = assets.right_semicircle,
    146 	hl = function()
    147 		return {
    148 			fg = mode_colors[vim.fn.mode()][2],
    149 			bg = sett.bkg
    150 		}
    151 	end,
    152 	enabled = function()
    153 		return not any_git_changes()
    154 	end
    155 }
    156 
    157 -- enable if git diffs are available
    158 components.active[1][5] = {
    159 	provider = assets.right_semicircle,
    160 	hl = function()
    161 		return {
    162 			fg = mode_colors[vim.fn.mode()][2],
    163 			bg = sett.diffs
    164 		}
    165 	end,
    166 	enabled = function()
    167 		return any_git_changes()
    168 	end
    169 }
    170 -- Current vi mode ------>
    171 
    172 -- Diffs ------>
    173 components.active[1][6] = {
    174 	provider = "git_diff_added",
    175 	hl = {
    176 		fg = sett.bkg,
    177 		bg = sett.diffs,
    178 	},
    179 	icon = "  ",
    180 }
    181 
    182 components.active[1][7] = {
    183 	provider = "git_diff_changed",
    184 	hl = {
    185 		fg = sett.bkg,
    186 		bg = sett.diffs,
    187 	},
    188 	icon = "  ",
    189 }
    190 
    191 components.active[1][8] = {
    192 	provider = "git_diff_removed",
    193 	hl = {
    194 		fg = sett.bkg,
    195 		bg = sett.diffs,
    196 	},
    197 	icon = "  ",
    198 }
    199 
    200 components.active[1][9] = {
    201 	provider = assets.right_semicircle,
    202 	hl = {
    203 		fg = sett.diffs,
    204 		bg = sett.bkg,
    205 	},
    206 	enabled = function()
    207 		return any_git_changes()
    208 	end
    209 }
    210 -- Diffs ------>
    211 
    212 -- Extras ------>
    213 
    214 -- file progess
    215 components.active[1][10] = {
    216 	provider = function()
    217 		local current_line = vim.fn.line(".")
    218 		local total_line = vim.fn.line("$")
    219 
    220 		if current_line == 1 then
    221 			return " Top "
    222 		elseif current_line == vim.fn.line("$") then
    223 			return " Bot "
    224 		end
    225 		local result, _ = math.modf((current_line / total_line) * 100)
    226 		return " " .. result .. "%% "
    227 	end,
    228 	-- enabled = shortline or function(winid)
    229 	-- 	return vim.api.nvim_win_get_width(winid) > 90
    230 	-- end,
    231 	hl = {
    232 		fg = sett.extras,
    233 		bg = sett.bkg
    234 	},
    235 	left_sep = invi_sep,
    236 }
    237 
    238 -- position
    239 components.active[1][11] = {
    240 	provider = "position",
    241 	-- enabled = shortline or function(winid)
    242 	-- 	return vim.api.nvim_win_get_width(winid) > 90
    243 	-- end,
    244 	hl = {
    245 		fg = sett.extras,
    246 		bg = sett.bkg
    247 	},
    248 	left_sep = invi_sep,
    249 }
    250 -- Extras ------>
    251 
    252 -- ######## Left
    253 
    254 -- ######## Center
    255 
    256 -- Diagnostics ------>
    257 -- workspace loader
    258 components.active[2][1] = {
    259 	provider = function()
    260 		local Lsp = vim.lsp.util.get_progress_messages()[1]
    261 
    262 		if Lsp then
    263 			local msg = Lsp.message or ""
    264 			local percentage = Lsp.percentage or 0
    265 			local title = Lsp.title or ""
    266 			local spinners = {
    267 				"",
    268 				"",
    269 				"",
    270 			}
    271 			local success_icon = {
    272 				"",
    273 				"",
    274 				"",
    275 			}
    276 			local ms = vim.loop.hrtime() / 1000000
    277 			local frame = math.floor(ms / 120) % #spinners
    278 
    279 			if percentage >= 70 then
    280 				return string.format(" %%<%s %s %s (%s%%%%) ", success_icon[frame + 1], title, msg, percentage)
    281 			end
    282 
    283 			return string.format(" %%<%s %s %s (%s%%%%) ", spinners[frame + 1], title, msg, percentage)
    284 		end
    285 
    286 		return ""
    287 	end,
    288 	enabled = shortline or function(winid)
    289 		return vim.api.nvim_win_get_width(winid) > 80
    290 	end,
    291 	hl = {
    292 		fg = colors.rosewater,
    293 		bg = sett.bkg
    294 	},
    295 }
    296 
    297 -- genral diagnostics (errors, warnings. info and hints)
    298 components.active[2][2] = {
    299 	provider = "diagnostic_errors",
    300 	enabled = function()
    301 		return lsp.diagnostics_exist(lsp_severity.ERROR)
    302 	end,
    303 
    304 	hl = {
    305 		fg = colors.red,
    306 		bg = sett.bkg,
    307 	},
    308 	icon = "  ",
    309 }
    310 
    311 components.active[2][3] = {
    312 	provider = "diagnostic_warnings",
    313 	enabled = function()
    314 		return lsp.diagnostics_exist(lsp_severity.WARN)
    315 	end,
    316 	hl = {
    317 		fg = colors.yellow,
    318 		bg = sett.bkg,
    319 	},
    320 	icon = "  ",
    321 }
    322 
    323 components.active[2][4] = {
    324 	provider = "diagnostic_info",
    325 	enabled = function()
    326 		return lsp.diagnostics_exist(lsp_severity.INFO)
    327 	end,
    328 	hl = {
    329 		fg = colors.sky,
    330 		bg = sett.bkg,
    331 	},
    332 	icon = "  ",
    333 }
    334 
    335 components.active[2][5] = {
    336 	provider = "diagnostic_hints",
    337 	enabled = function()
    338 		return lsp.diagnostics_exist(lsp_severity.HINT)
    339 	end,
    340 	hl = {
    341 		fg = colors.rosewater,
    342 		bg = sett.bkg,
    343 	},
    344 	icon = "  ",
    345 }
    346 -- Diagnostics ------>
    347 
    348 -- ######## Center
    349 
    350 -- ######## Right
    351 
    352 components.active[3][1] = {
    353 	provider = "git_branch",
    354 	enabled = shortline or function(winid)
    355 		return vim.api.nvim_win_get_width(winid) > 70
    356 	end,
    357 	hl = {
    358 		fg = sett.extras,
    359 		bg = sett.bkg
    360 	},
    361 	icon = "   ",
    362 	left_sep = invi_sep,
    363 	right_sep = invi_sep,
    364 }
    365 
    366 components.active[3][2] = {
    367 	provider = function()
    368 		if next(vim.lsp.buf_get_clients()) ~= nil then
    369 			return " "
    370 		else
    371 			return ""
    372 		end
    373 	end,
    374 	hl = {
    375 		fg = sett.extras,
    376 		bg = sett.bkg
    377 	},
    378 	right_sep = invi_sep,
    379 }
    380 
    381 components.active[3][3] = {
    382 	provider = function()
    383 		local filename = vim.fn.expand("%:t")
    384 		local extension = vim.fn.expand("%:e")
    385 		local icon = require("nvim-web-devicons").get_icon(filename, extension)
    386 		if icon == nil then
    387 			icon = "   "
    388 			return icon
    389 		end
    390 		return " " .. icon .. " " .. filename .. " "
    391 	end,
    392 	enabled = shortline or function(winid)
    393 		return vim.api.nvim_win_get_width(winid) > 70
    394 	end,
    395 	hl = {
    396 		fg = sett.bkg,
    397 		bg = sett.curr_file,
    398 	},
    399 	left_sep = {
    400 		str = assets.left_semicircle,
    401 		hl = {
    402 			fg = sett.curr_file,
    403 			bg = sett.bkg,
    404 		},
    405 	},
    406 }
    407 
    408 components.active[3][4] = {
    409 	provider = function()
    410 		local dir_name = vim.fn.fnamemodify(vim.fn.getcwd(), ":t")
    411 		return "  " .. dir_name .. " "
    412 	end,
    413 
    414 	enabled = shortline or function(winid)
    415 		return vim.api.nvim_win_get_width(winid) > 80
    416 	end,
    417 
    418 	hl = {
    419 		fg = sett.bkg,
    420 		bg = sett.curr_dir,
    421 	},
    422 	left_sep = {
    423 		str = assets.left_semicircle,
    424 		hl = {
    425 			fg = sett.curr_dir,
    426 			bg = sett.curr_file,
    427 		},
    428 	},
    429 }
    430 -- ######## Right
    431 
    432 return components