lualine.nvim/lua/lualine/component.lua

173 lines
6.0 KiB
Lua

-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local highlight = require 'lualine.highlight'
-- Used to provide a unique id for each component
local component_no = 1
local Component = {
-- Creates a new component
new = function(self, options, child)
local new_component = {}
new_component.options = options
new_component._parent = child or self
setmetatable(new_component, {__index = new_component._parent})
-- Operation that are required for creating new components but not for inheritence
if options ~= nil then
component_no = component_no + 1
if not options.component_name then
new_component.options.component_name = tostring(component_no)
end
new_component.component_no = component_no
new_component:set_separator()
new_component:create_option_highlights()
end
return new_component
end,
set_separator = function(self)
if self.options.separator == nil then
if self.options.component_separators then
if self.options.self.section < 'lualine_x' then
self.options.separator = self.options.component_separators[1]
else
self.options.separator = self.options.component_separators[2]
end
end
end
end,
create_option_highlights = function(self)
-- set custom highlights
if type(self.options.color) == 'table' then
self.options.color_highlight = highlight.create_component_highlight_group(
self.options.color,
self.options.component_name,
self.options)
elseif type(self.options.color) == 'string' then
self.options.color_highlight_link = self.options.color
end
end,
-- set upper or lower case
apply_case = function(self)
-- Donn't work on components that emit vim statusline escaped chars
if self.status:find('%%') and not self.status:find('%%%%') then return end
if self.options.upper == true then
self.status = self.status:upper()
elseif self.options.lower == true then
self.status = self.status:lower()
end
end,
-- Adds spaces to left and right of a component
apply_padding = function(self)
local l_padding = (self.options.left_padding or self.options.padding or 1)
local r_padding = (self.options.right_padding or self.options.padding or 1)
if l_padding then
if self.status:find('%%#.*#') == 1 then
-- When component has changed the highlight at begining
-- we will add the padding after the highlight
local pre_highlight =
vim.fn.matchlist(self.status, [[\(%#.\{-\}#\)]])[2]
self.status = pre_highlight .. string.rep(' ', l_padding) ..
self.status:sub(#pre_highlight + 1, #self.status)
else
self.status = string.rep(' ', l_padding) .. self.status
end
end
if r_padding then self.status = self.status .. string.rep(' ', r_padding) end
end,
-- Applies custom highlights for component
apply_highlights = function(self, default_highlight)
if self.options.color_highlight then
self.status = highlight.component_format_highlight(
self.options.color_highlight) .. self.status
elseif self.options.color_highlight_link then
self.status = '%#' .. self.options.color_highlight_link .. '#' ..
self.status
end
self.status = self.status .. default_highlight
end,
-- Apply icon in front of component
apply_icon = function(self)
if self.options.icons_enabled and self.options.icon then
self.status = self.options.icon .. ' ' .. self.status
end
end,
-- Apply separator at end of component only when
-- custom highlights haven't affected background
apply_separator = function(self)
local separator = self.options.separator
if type(separator) == 'table' then
if self.options.separator[2] == '' then
if self.options.self.section < 'lualine_x' then
separator = self.options.component_separators[1]
else
separator = self.options.component_separators[2]
end
else
return
end
end
if separator and #separator > 0 then
self.status = self.status .. separator
self.applied_separator = separator
end
end,
apply_section_separators = function(self)
if type(self.options.separator) ~= 'table' then return end
if self.options.separator[1] ~= '' then
self.status = string.format('%%s{%s}%s', self.options.separator[1],
self.status)
self.strip_previous_separator = true
end
if self.options.separator[2] ~= '' then
self.status = string.format('%s%%S{%s}', self.status,
self.options.separator[2])
end
end,
strip_separator = function(self)
if not self.applied_separator then self.applied_separator = '' end
self.status = self.status:sub(1, (#self.status -
(#self.applied_separator)))
self.applied_separator = nil
return self.status
end,
-- variable to store component output for manupulation
status = '',
-- Actual function the updates a component . Must be overwritten with component functionality
-- luacheck: push no unused args
update_status = function(self) end,
-- luacheck: pop
-- Driver code of the class
draw = function(self, default_highlight)
self.status = ''
if self.options.condition ~= nil and self.options.condition() ~= true then
return self.status
end
local status = self:update_status()
if self.options.format then status = self.options.format(status or '') end
if type(status) == 'string' and #status > 0 then
self.status = status
self:apply_icon()
self:apply_case()
self:apply_padding()
self:apply_section_separators()
self:apply_highlights(default_highlight)
self:apply_separator()
end
return self.status
end
}
return Component