Refactor: Components now use OOP style (#141)
This commit is contained in:
parent
2b32fb090f
commit
1b81b0021f
|
@ -0,0 +1,135 @@
|
||||||
|
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 type(self.options.separator) ~= 'string' 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 self.options.color then
|
||||||
|
self.options.color_highlight = highlight.create_component_highlight_group(
|
||||||
|
self.options.color,
|
||||||
|
self.options.component_name,
|
||||||
|
self.options)
|
||||||
|
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
|
||||||
|
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)
|
||||||
|
if self.options.separator and #self.options.separator > 0 then
|
||||||
|
self.status = self.status .. self.options.separator
|
||||||
|
self.applied_separator = self.options.separator
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
|
||||||
|
strip_separator = function(self, default_highlight)
|
||||||
|
if not default_highlight then default_highlight = '' end
|
||||||
|
if not self.applied_separator then self.applied_separator = '' end
|
||||||
|
self.status = self.status:sub(1, (#self.status -
|
||||||
|
(#self.applied_separator +
|
||||||
|
#default_highlight)))
|
||||||
|
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
|
||||||
|
update_status = function(self) end,
|
||||||
|
|
||||||
|
-- Driver code of the class
|
||||||
|
draw = function(self, default_highlight)
|
||||||
|
self.status = ''
|
||||||
|
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_highlights(default_highlight)
|
||||||
|
self:apply_separator()
|
||||||
|
end
|
||||||
|
return self.status
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
return Component
|
|
@ -1,12 +1,31 @@
|
||||||
-- Copyright (c) 2020-2021 shadmansaleh
|
-- Copyright (c) 2020-2021 shadmansaleh
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
local git_branch
|
local Branch = require('lualine.component'):new()
|
||||||
|
|
||||||
|
-- vars
|
||||||
|
Branch.git_branch = ''
|
||||||
-- os specific path separator
|
-- os specific path separator
|
||||||
local sep = package.config:sub(1, 1)
|
Branch.sep = package.config:sub(1, 1)
|
||||||
|
-- event watcher to watch head file
|
||||||
|
Branch.file_changed = vim.loop.new_fs_event()
|
||||||
|
|
||||||
|
-- Initilizer
|
||||||
|
Branch.new = function(self, options, child)
|
||||||
|
local new_branch = self._parent:new(options, child or Branch)
|
||||||
|
if not new_branch.options.icon then
|
||||||
|
new_branch.options.icon = '' -- e0a0
|
||||||
|
end
|
||||||
|
-- run watch head on load so branch is present when component is loaded
|
||||||
|
Branch.update_branch()
|
||||||
|
-- update branch state of BufEnter as different Buffer may be on different repos
|
||||||
|
vim.cmd [[autocmd BufEnter * lua require'lualine.components.branch'.update_branch()]]
|
||||||
|
return new_branch
|
||||||
|
end
|
||||||
|
|
||||||
|
Branch.update_status = function() return Branch.git_branch end
|
||||||
|
|
||||||
-- returns full path to git directory for current directory
|
-- returns full path to git directory for current directory
|
||||||
local function find_git_dir()
|
function Branch.find_git_dir()
|
||||||
-- get file dir so we can search from that dir
|
-- get file dir so we can search from that dir
|
||||||
local file_dir = vim.fn.expand('%:p:h') .. ';'
|
local file_dir = vim.fn.expand('%:p:h') .. ';'
|
||||||
-- find .git/ folder genaral case
|
-- find .git/ folder genaral case
|
||||||
|
@ -23,7 +42,7 @@ local function find_git_dir()
|
||||||
git_dir = git_dir:match('gitdir: (.+)$')
|
git_dir = git_dir:match('gitdir: (.+)$')
|
||||||
file:close()
|
file:close()
|
||||||
-- submodule / relative file path
|
-- submodule / relative file path
|
||||||
if git_dir:sub(1, 1) ~= sep and not git_dir:match('^%a:.*$') then
|
if git_dir:sub(1, 1) ~= Branch.sep and not git_dir:match('^%a:.*$') then
|
||||||
git_dir = git_file:match('(.*).git') .. git_dir
|
git_dir = git_file:match('(.*).git') .. git_dir
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -31,58 +50,37 @@ local function find_git_dir()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- sets git_branch veriable to branch name or commit hash if not on branch
|
-- sets git_branch veriable to branch name or commit hash if not on branch
|
||||||
local function get_git_head(head_file)
|
function Branch.get_git_head(head_file)
|
||||||
local f_head = io.open(head_file)
|
local f_head = io.open(head_file)
|
||||||
if f_head then
|
if f_head then
|
||||||
local HEAD = f_head:read()
|
local HEAD = f_head:read()
|
||||||
f_head:close()
|
f_head:close()
|
||||||
local branch = HEAD:match('ref: refs/heads/(.+)$')
|
local branch = HEAD:match('ref: refs/heads/(.+)$')
|
||||||
if branch then
|
if branch then
|
||||||
git_branch = branch
|
Branch.git_branch = branch
|
||||||
else
|
else
|
||||||
git_branch = HEAD:sub(1, 6)
|
Branch.git_branch = HEAD:sub(1, 6)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- event watcher to watch head file
|
-- Update branch
|
||||||
local file_changed = vim.loop.new_fs_event()
|
function Branch.update_branch()
|
||||||
local function watch_head()
|
Branch.file_changed:stop()
|
||||||
file_changed:stop()
|
local git_dir = Branch.find_git_dir()
|
||||||
local git_dir = find_git_dir()
|
|
||||||
if #git_dir > 0 then
|
if #git_dir > 0 then
|
||||||
local head_file = git_dir .. sep .. 'HEAD'
|
local head_file = git_dir .. Branch.sep .. 'HEAD'
|
||||||
get_git_head(head_file)
|
Branch.get_git_head(head_file)
|
||||||
file_changed:start(head_file, {}, vim.schedule_wrap(
|
Branch.file_changed:start(head_file, {}, vim.schedule_wrap(
|
||||||
function()
|
function()
|
||||||
-- reset file-watch
|
-- reset file-watch
|
||||||
watch_head()
|
Branch.update_branch()
|
||||||
end))
|
end))
|
||||||
else
|
else
|
||||||
-- set to nil when git dir was not found
|
-- set to '' when git dir was not found
|
||||||
git_branch = nil
|
Branch.git_branch = ''
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function branch(options)
|
return Branch
|
||||||
if not options.icon then
|
|
||||||
options.icon = '' -- e0a0
|
|
||||||
end
|
|
||||||
|
|
||||||
return function()
|
|
||||||
if not git_branch or #git_branch == 0 then return '' end
|
|
||||||
return git_branch
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- run watch head on load so branch is present when component is loaded
|
|
||||||
watch_head()
|
|
||||||
|
|
||||||
-- update branch state of BufEnter as different Buffer may be on different repos
|
|
||||||
vim.cmd [[autocmd BufEnter * lua require'lualine.components.branch'.lualine_branch_update()]]
|
|
||||||
|
|
||||||
return {
|
|
||||||
init = function(options) return branch(options) end,
|
|
||||||
lualine_branch_update = watch_head
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,13 +3,106 @@
|
||||||
local highlight = require('lualine.highlight')
|
local highlight = require('lualine.highlight')
|
||||||
local utils = require('lualine.utils.utils')
|
local utils = require('lualine.utils.utils')
|
||||||
|
|
||||||
|
local Diagnostics = require('lualine.component'):new()
|
||||||
|
|
||||||
-- LuaFormatter off
|
-- LuaFormatter off
|
||||||
local default_color_error = '#e32636'
|
Diagnostics.default_colors = {
|
||||||
local default_color_warn = '#ffdf00'
|
error = '#e32636',
|
||||||
local default_color_info = '#ffffff'
|
warn = '#ffdf00',
|
||||||
|
info = '#ffffff',
|
||||||
|
}
|
||||||
-- LuaFormatter on
|
-- LuaFormatter on
|
||||||
|
|
||||||
local diagnostic_sources = {
|
-- Initializer
|
||||||
|
Diagnostics.new = function(self, options, child)
|
||||||
|
local new_diagnostics = self._parent:new(options, child or Diagnostics)
|
||||||
|
local default_symbols = new_diagnostics.options.icons_enabled and {
|
||||||
|
error = ' ', -- xf659
|
||||||
|
warn = ' ', -- xf529
|
||||||
|
info = ' ' -- xf7fc
|
||||||
|
} or {error = 'E:', warn = 'W:', info = 'I:'}
|
||||||
|
new_diagnostics.symbols = vim.tbl_extend('force', default_symbols,
|
||||||
|
new_diagnostics.options.symbols or {})
|
||||||
|
if new_diagnostics.options.sources == nil then
|
||||||
|
print('no sources for diagnostics configured')
|
||||||
|
return ''
|
||||||
|
end
|
||||||
|
if new_diagnostics.options.sections == nil then
|
||||||
|
new_diagnostics.options.sections = {'error', 'warn', 'info'}
|
||||||
|
end
|
||||||
|
if new_diagnostics.options.colored == nil then
|
||||||
|
new_diagnostics.options.colored = true
|
||||||
|
end
|
||||||
|
-- apply colors
|
||||||
|
if not new_diagnostics.options.color_error then
|
||||||
|
new_diagnostics.options.color_error =
|
||||||
|
utils.extract_highlight_colors('DiffDelete', 'guifg') or
|
||||||
|
Diagnostics.default_colors.error
|
||||||
|
end
|
||||||
|
if not new_diagnostics.options.color_warn then
|
||||||
|
new_diagnostics.options.color_warn =
|
||||||
|
utils.extract_highlight_colors('DiffText', 'guifg') or
|
||||||
|
Diagnostics.default_colors.warn
|
||||||
|
end
|
||||||
|
if not new_diagnostics.options.color_info then
|
||||||
|
new_diagnostics.options.color_info =
|
||||||
|
utils.extract_highlight_colors('Normal', 'guifg') or
|
||||||
|
Diagnostics.default_colors.info
|
||||||
|
end
|
||||||
|
|
||||||
|
if new_diagnostics.options.colored then
|
||||||
|
new_diagnostics.highlight_groups = {
|
||||||
|
error = highlight.create_component_highlight_group(
|
||||||
|
{fg = new_diagnostics.options.color_error}, 'diagnostics_error',
|
||||||
|
new_diagnostics.options),
|
||||||
|
warn = highlight.create_component_highlight_group(
|
||||||
|
{fg = new_diagnostics.options.color_warn}, 'diagnostics_warn',
|
||||||
|
new_diagnostics.options),
|
||||||
|
info = highlight.create_component_highlight_group(
|
||||||
|
{fg = new_diagnostics.options.color_info}, 'diagnostics_info',
|
||||||
|
new_diagnostics.options)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
return new_diagnostics
|
||||||
|
end
|
||||||
|
|
||||||
|
Diagnostics.update_status = function(self)
|
||||||
|
local error_count, warning_count, info_count = 0, 0, 0
|
||||||
|
local diagnostic_data = self.get_diagnostics(self.options.sources)
|
||||||
|
for _, data in pairs(diagnostic_data) do
|
||||||
|
error_count = error_count + data.error
|
||||||
|
warning_count = warning_count + data.warn
|
||||||
|
info_count = info_count + data.info
|
||||||
|
end
|
||||||
|
local result = {}
|
||||||
|
local data = {error = error_count, warn = warning_count, info = info_count}
|
||||||
|
if self.options.colored then
|
||||||
|
local colors = {}
|
||||||
|
for name, hl in pairs(self.highlight_groups) do
|
||||||
|
colors[name] = highlight.component_format_highlight(hl)
|
||||||
|
end
|
||||||
|
for _, section in ipairs(self.options.sections) do
|
||||||
|
if data[section] ~= nil and data[section] > 0 then
|
||||||
|
table.insert(result,
|
||||||
|
colors[section] .. self.symbols[section] .. data[section])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for _, section in ipairs(self.options.sections) do
|
||||||
|
if data[section] ~= nil and data[section] > 0 then
|
||||||
|
table.insert(result, self.symbols[section] .. data[section])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if result[1] ~= nil then
|
||||||
|
return table.concat(result, ' ')
|
||||||
|
else
|
||||||
|
return ''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Diagnostics.diagnostic_sources = {
|
||||||
nvim_lsp = function()
|
nvim_lsp = function()
|
||||||
local error_count = vim.lsp.diagnostic.get_count(0, 'Error')
|
local error_count = vim.lsp.diagnostic.get_count(0, 'Error')
|
||||||
local warning_count = vim.lsp.diagnostic.get_count(0, 'Warning')
|
local warning_count = vim.lsp.diagnostic.get_count(0, 'Warning')
|
||||||
|
@ -32,21 +125,14 @@ local diagnostic_sources = {
|
||||||
else
|
else
|
||||||
return 0, 0, 0
|
return 0, 0, 0
|
||||||
end
|
end
|
||||||
end,
|
|
||||||
vim_lsp = function()
|
|
||||||
local ok, data = pcall(vim.fn['lsp#get_buffer_diagnostics_counts'])
|
|
||||||
if ok then
|
|
||||||
return data.error, data.warning, data.information
|
|
||||||
else
|
|
||||||
return 0, 0, 0
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
local function get_diagnostics(sources)
|
Diagnostics.get_diagnostics = function(sources)
|
||||||
local result = {}
|
local result = {}
|
||||||
for index, source in ipairs(sources) do
|
for index, source in ipairs(sources) do
|
||||||
local error_count, warning_count, info_count = diagnostic_sources[source]()
|
local error_count, warning_count, info_count =
|
||||||
|
Diagnostics.diagnostic_sources[source]()
|
||||||
result[index] = {
|
result[index] = {
|
||||||
error = error_count,
|
error = error_count,
|
||||||
warn = warning_count,
|
warn = warning_count,
|
||||||
|
@ -56,84 +142,4 @@ local function get_diagnostics(sources)
|
||||||
return result
|
return result
|
||||||
end
|
end
|
||||||
|
|
||||||
local function diagnostics(options)
|
return Diagnostics
|
||||||
local default_symbols = options.icons_enabled and {
|
|
||||||
error = ' ', -- xf659
|
|
||||||
warn = ' ', -- xf529
|
|
||||||
info = ' ' -- xf7fc
|
|
||||||
} or {error = 'E:', warn = 'W:', info = 'I:'}
|
|
||||||
options.symbols = vim.tbl_extend('force', default_symbols,
|
|
||||||
options.symbols or {})
|
|
||||||
if options.sources == nil then
|
|
||||||
print('no sources for diagnostics configured')
|
|
||||||
return ''
|
|
||||||
end
|
|
||||||
if options.sections == nil then options.sections = {'error', 'warn', 'info'} end
|
|
||||||
if options.colored == nil then options.colored = true end
|
|
||||||
-- apply colors
|
|
||||||
if not options.color_error then
|
|
||||||
options.color_error =
|
|
||||||
utils.extract_highlight_colors('DiffDelete', 'guifg') or
|
|
||||||
default_color_error
|
|
||||||
end
|
|
||||||
if not options.color_warn then
|
|
||||||
options.color_warn = utils.extract_highlight_colors('DiffText', 'guifg') or
|
|
||||||
default_color_warn
|
|
||||||
end
|
|
||||||
if not options.color_info then
|
|
||||||
options.color_info = utils.extract_highlight_colors('Normal', 'guifg') or
|
|
||||||
default_color_info
|
|
||||||
end
|
|
||||||
|
|
||||||
local highlight_groups = {}
|
|
||||||
if options.colored then
|
|
||||||
highlight_groups = {
|
|
||||||
error = highlight.create_component_highlight_group(
|
|
||||||
{fg = options.color_error}, 'diagnostics_error', options),
|
|
||||||
warn = highlight.create_component_highlight_group(
|
|
||||||
{fg = options.color_warn}, 'diagnostics_warn', options),
|
|
||||||
info = highlight.create_component_highlight_group(
|
|
||||||
{fg = options.color_info}, 'diagnostics_info', options)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
return function()
|
|
||||||
local error_count, warning_count, info_count = 0, 0, 0
|
|
||||||
local diagnostic_data = get_diagnostics(options.sources)
|
|
||||||
for _, data in pairs(diagnostic_data) do
|
|
||||||
error_count = error_count + data.error
|
|
||||||
warning_count = warning_count + data.warn
|
|
||||||
info_count = info_count + data.info
|
|
||||||
end
|
|
||||||
local result = {}
|
|
||||||
local data = {error = error_count, warn = warning_count, info = info_count}
|
|
||||||
if options.colored then
|
|
||||||
local colors = {}
|
|
||||||
for name, hl in pairs(highlight_groups) do
|
|
||||||
colors[name] = highlight.component_format_highlight(hl)
|
|
||||||
end
|
|
||||||
for _, section in ipairs(options.sections) do
|
|
||||||
if data[section] ~= nil and data[section] > 0 then
|
|
||||||
table.insert(result, colors[section] .. options.symbols[section] ..
|
|
||||||
data[section])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
for _, section in ipairs(options.sections) do
|
|
||||||
if data[section] ~= nil and data[section] > 0 then
|
|
||||||
table.insert(result, options.symbols[section] .. data[section])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if result[1] ~= nil then
|
|
||||||
return table.concat(result, ' ')
|
|
||||||
else
|
|
||||||
return ''
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
init = function(options) return diagnostics(options) end,
|
|
||||||
get_diagnostics = get_diagnostics
|
|
||||||
}
|
|
||||||
|
|
|
@ -4,13 +4,120 @@ local async = require 'lualine.utils.async'
|
||||||
local utils = require 'lualine.utils.utils'
|
local utils = require 'lualine.utils.utils'
|
||||||
local highlight = require 'lualine.highlight'
|
local highlight = require 'lualine.highlight'
|
||||||
|
|
||||||
|
local Diff = require('lualine.component'):new()
|
||||||
|
|
||||||
|
-- Vars
|
||||||
-- variable to store git diff stats
|
-- variable to store git diff stats
|
||||||
local git_diff = nil
|
Diff.git_diff = nil
|
||||||
-- accumulates async output to process in the end
|
-- accumulates async output to process in the end
|
||||||
local diff_data = ''
|
Diff.diff_data = ''
|
||||||
|
-- variable to store git_diff getter async function
|
||||||
|
Diff.get_git_diff = nil
|
||||||
|
-- default colors
|
||||||
|
Diff.default_colors = {
|
||||||
|
added = '#f0e130',
|
||||||
|
removed = '#90ee90',
|
||||||
|
modified = '#ff0038'
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Initializer
|
||||||
|
Diff.new = function(self, options, child)
|
||||||
|
local new_instence = self._parent:new(options, child or Diff)
|
||||||
|
local default_symbols = {added = '+', modified = '~', removed = '-'}
|
||||||
|
new_instence.options.symbols = vim.tbl_extend('force', default_symbols,
|
||||||
|
new_instence.options.symbols or
|
||||||
|
{})
|
||||||
|
if new_instence.options.colored == nil then
|
||||||
|
new_instence.options.colored = true
|
||||||
|
end
|
||||||
|
-- apply colors
|
||||||
|
if not new_instence.options.color_added then
|
||||||
|
new_instence.options.color_added = utils.extract_highlight_colors('DiffAdd',
|
||||||
|
'guifg') or
|
||||||
|
Diff.default_colors.added
|
||||||
|
end
|
||||||
|
if not new_instence.options.color_modified then
|
||||||
|
new_instence.options.color_modified =
|
||||||
|
utils.extract_highlight_colors('DiffChange', 'guifg') or
|
||||||
|
Diff.default_colors.modified
|
||||||
|
end
|
||||||
|
if not new_instence.options.color_removed then
|
||||||
|
new_instence.options.color_removed =
|
||||||
|
utils.extract_highlight_colors('DiffDelete', 'guifg') or
|
||||||
|
Diff.default_colors.removed
|
||||||
|
end
|
||||||
|
|
||||||
|
-- create highlights and save highlight_name in highlights table
|
||||||
|
if new_instence.options.colored then
|
||||||
|
new_instence.highlights = {
|
||||||
|
added = highlight.create_component_highlight_group(
|
||||||
|
{fg = new_instence.options.color_added}, 'diff_added',
|
||||||
|
new_instence.options),
|
||||||
|
modified = highlight.create_component_highlight_group(
|
||||||
|
{fg = new_instence.options.color_modified}, 'diff_modified',
|
||||||
|
new_instence.options),
|
||||||
|
removed = highlight.create_component_highlight_group(
|
||||||
|
{fg = new_instence.options.color_removed}, 'diff_removed',
|
||||||
|
new_instence.options)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_exec([[
|
||||||
|
autocmd lualine BufEnter * lua require'lualine.components.diff'.update_git_diff_getter()
|
||||||
|
autocmd lualine BufEnter * lua require'lualine.components.diff'.update_git_diff()
|
||||||
|
autocmd lualine BufWritePost * lua require'lualine.components.diff'.update_git_diff()
|
||||||
|
]], false)
|
||||||
|
|
||||||
|
return new_instence
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Function that runs everytime statusline is updated
|
||||||
|
Diff.update_status = function(self)
|
||||||
|
if Diff.git_diff == nil then return '' end
|
||||||
|
|
||||||
|
local colors = {}
|
||||||
|
if self.options.colored then
|
||||||
|
-- load the highlights and store them in colors table
|
||||||
|
for name, highlight_name in pairs(self.highlights) do
|
||||||
|
colors[name] = highlight.component_format_highlight(highlight_name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local result = {}
|
||||||
|
-- loop though data and load available sections in result table
|
||||||
|
for _, name in ipairs {'added', 'modified', 'removed'} do
|
||||||
|
if Diff.git_diff[name] and Diff.git_diff[name] > 0 then
|
||||||
|
if self.options.colored then
|
||||||
|
table.insert(result, colors[name] .. self.options.symbols[name] ..
|
||||||
|
Diff.git_diff[name])
|
||||||
|
else
|
||||||
|
table.insert(result, self.options.symbols[name] .. Diff.git_diff[name])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #result > 0 then
|
||||||
|
return table.concat(result, ' ')
|
||||||
|
else
|
||||||
|
return ''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Api to get git sign count
|
||||||
|
-- scheme :
|
||||||
|
-- {
|
||||||
|
-- added = added_count,
|
||||||
|
-- modified = modified_count,
|
||||||
|
-- removed = removed_count,
|
||||||
|
-- }
|
||||||
|
-- error_code = { added = -1, modified = -1, removed = -1 }
|
||||||
|
function Diff.get_sign_count()
|
||||||
|
Diff.update_git_diff_getter()
|
||||||
|
Diff.update_git_diff()
|
||||||
|
return Diff.git_diff or {added = -1, modified = -1, removed = -1}
|
||||||
|
end
|
||||||
|
|
||||||
-- process diff data and update git_diff{ added, removed, modified }
|
-- process diff data and update git_diff{ added, removed, modified }
|
||||||
local function process_diff(data)
|
function Diff.process_diff(data)
|
||||||
-- Adapted from https://github.com/wbthomason/nvim-vcs.lua
|
-- Adapted from https://github.com/wbthomason/nvim-vcs.lua
|
||||||
local added, removed, modified = 0, 0, 0
|
local added, removed, modified = 0, 0, 0
|
||||||
for line in vim.gsplit(data, '\n') do
|
for line in vim.gsplit(data, '\n') do
|
||||||
|
@ -34,149 +141,50 @@ local function process_diff(data)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
git_diff = {added = added, modified = modified, removed = removed}
|
Diff.git_diff = {added = added, modified = modified, removed = removed}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- variable to store git_diff getter async function
|
|
||||||
local get_git_diff = nil
|
|
||||||
|
|
||||||
-- Updates the async function for current file
|
-- Updates the async function for current file
|
||||||
local function update_git_diff_getter()
|
function Diff.update_git_diff_getter()
|
||||||
-- stop older function properly before overwritting it
|
-- stop older function properly before overwritting it
|
||||||
if get_git_diff then get_git_diff:stop() end
|
if Diff.get_git_diff then Diff.get_git_diff:stop() end
|
||||||
-- Donn't show git diff when current buffer doesn't have a filename
|
-- Donn't show git diff when current buffer doesn't have a filename
|
||||||
if #vim.fn.expand('%') == 0 then
|
if #vim.fn.expand('%') == 0 then
|
||||||
get_git_diff = nil;
|
Diff.get_git_diff = nil;
|
||||||
git_diff = nil;
|
Diff.git_diff = nil;
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
get_git_diff = async:new({
|
Diff.get_git_diff = async:new({
|
||||||
cmd = string.format(
|
cmd = string.format(
|
||||||
[[git -C %s --no-pager diff --no-color --no-ext-diff -U0 -- %s]],
|
[[git -C %s --no-pager diff --no-color --no-ext-diff -U0 -- %s]],
|
||||||
vim.fn.expand('%:h'), vim.fn.expand('%:t')),
|
vim.fn.expand('%:h'), vim.fn.expand('%:t')),
|
||||||
on_stdout = function(_, data)
|
on_stdout = function(_, data)
|
||||||
if data then diff_data = diff_data .. data end
|
if data then Diff.diff_data = Diff.diff_data .. data end
|
||||||
end,
|
end,
|
||||||
on_stderr = function(_, data)
|
on_stderr = function(_, data)
|
||||||
if data then
|
if data then
|
||||||
git_diff = nil
|
Diff.git_diff = nil
|
||||||
diff_data = ''
|
Diff.diff_data = ''
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
on_exit = function()
|
on_exit = function()
|
||||||
if diff_data ~= '' then
|
if Diff.diff_data ~= '' then
|
||||||
process_diff(diff_data)
|
Diff.process_diff(Diff.diff_data)
|
||||||
else
|
else
|
||||||
git_diff = {added = 0, modified = 0, removed = 0}
|
Diff.git_diff = {added = 0, modified = 0, removed = 0}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Update git_diff veriable
|
-- Update git_diff veriable
|
||||||
local function update_git_diff()
|
function Diff.update_git_diff()
|
||||||
vim.schedule_wrap(function()
|
vim.schedule_wrap(function()
|
||||||
if get_git_diff then
|
if Diff.get_git_diff then
|
||||||
diff_data = ''
|
Diff.diff_data = ''
|
||||||
get_git_diff:start()
|
Diff.get_git_diff:start()
|
||||||
end
|
end
|
||||||
end)()
|
end)()
|
||||||
end
|
end
|
||||||
|
|
||||||
local default_color_added = '#f0e130'
|
return Diff
|
||||||
local default_color_removed = '#90ee90'
|
|
||||||
local default_color_modified = '#ff0038'
|
|
||||||
|
|
||||||
local function diff(options)
|
|
||||||
if options.colored == nil then options.colored = true end
|
|
||||||
-- apply colors
|
|
||||||
if not options.color_added then
|
|
||||||
options.color_added = utils.extract_highlight_colors('DiffAdd', 'guifg') or
|
|
||||||
default_color_added
|
|
||||||
end
|
|
||||||
if not options.color_modified then
|
|
||||||
options.color_modified = utils.extract_highlight_colors('DiffChange',
|
|
||||||
'guifg') or
|
|
||||||
default_color_modified
|
|
||||||
end
|
|
||||||
if not options.color_removed then
|
|
||||||
options.color_removed =
|
|
||||||
utils.extract_highlight_colors('DiffDelete', 'guifg') or
|
|
||||||
default_color_removed
|
|
||||||
end
|
|
||||||
|
|
||||||
local highlights = {}
|
|
||||||
|
|
||||||
-- create highlights and save highlight_name in highlights table
|
|
||||||
if options.colored then
|
|
||||||
highlights = {
|
|
||||||
added = highlight.create_component_highlight_group(
|
|
||||||
{fg = options.color_added}, 'diff_added', options),
|
|
||||||
modified = highlight.create_component_highlight_group(
|
|
||||||
{fg = options.color_modified}, 'diff_modified', options),
|
|
||||||
removed = highlight.create_component_highlight_group(
|
|
||||||
{fg = options.color_removed}, 'diff_removed', options)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
vim.api.nvim_exec([[
|
|
||||||
autocmd lualine BufEnter * lua require'lualine.components.diff'.update_git_diff_getter()
|
|
||||||
autocmd lualine BufEnter * lua require'lualine.components.diff'.update_git_diff()
|
|
||||||
autocmd lualine BufWritePost * lua require'lualine.components.diff'.update_git_diff()
|
|
||||||
]], false)
|
|
||||||
|
|
||||||
-- Function that runs everytime statusline is updated
|
|
||||||
return function()
|
|
||||||
if git_diff == nil then return '' end
|
|
||||||
|
|
||||||
local default_symbols = {added = '+', modified = '~', removed = '-'}
|
|
||||||
options.symbols = vim.tbl_extend('force', default_symbols,
|
|
||||||
options.symbols or {})
|
|
||||||
local colors = {}
|
|
||||||
if options.colored then
|
|
||||||
-- load the highlights and store them in colors table
|
|
||||||
for name, highlight_name in pairs(highlights) do
|
|
||||||
colors[name] = highlight.component_format_highlight(highlight_name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local result = {}
|
|
||||||
-- loop though data and load available sections in result table
|
|
||||||
for _, name in ipairs {'added', 'modified', 'removed'} do
|
|
||||||
if git_diff[name] and git_diff[name] > 0 then
|
|
||||||
if options.colored then
|
|
||||||
table.insert(result,
|
|
||||||
colors[name] .. options.symbols[name] .. git_diff[name])
|
|
||||||
else
|
|
||||||
table.insert(result, options.symbols[name] .. git_diff[name])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #result > 0 then
|
|
||||||
return table.concat(result, ' ')
|
|
||||||
else
|
|
||||||
return ''
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Api to get git sign count
|
|
||||||
-- scheme :
|
|
||||||
-- {
|
|
||||||
-- added = added_count,
|
|
||||||
-- modified = modified_count,
|
|
||||||
-- removed = removed_count,
|
|
||||||
-- }
|
|
||||||
-- error_code = { added = -1, modified = -1, removed = -1 }
|
|
||||||
local function get_sign_count()
|
|
||||||
update_git_diff_getter()
|
|
||||||
update_git_diff()
|
|
||||||
return git_diff or {added = -1, modified = -1, removed = -1}
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
init = function(options) return diff(options) end,
|
|
||||||
update_git_diff = update_git_diff,
|
|
||||||
update_git_diff_getter = update_git_diff_getter,
|
|
||||||
get_sign_count = get_sign_count
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
-- Copyright (c) 2020-2021 hoob3rt
|
-- Copyright (c) 2020-2021 hoob3rt
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
local function encoding()
|
local Encoding = require('lualine.component'):new()
|
||||||
local data = [[%{strlen(&fenc)?&fenc:&enc}]]
|
|
||||||
return data
|
|
||||||
end
|
|
||||||
|
|
||||||
return encoding
|
Encoding.update_status = function() return [[%{strlen(&fenc)?&fenc:&enc}]] end
|
||||||
|
|
||||||
|
return Encoding
|
||||||
|
|
|
@ -1,22 +1,19 @@
|
||||||
-- Copyright (c) 2020-2021 shadmansaleh
|
-- Copyright (c) 2020-2021 shadmansaleh
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
local function fileformat(options)
|
local FileFormat = require('lualine.component'):new()
|
||||||
local icon_linux = '' -- e712
|
|
||||||
local icon_windos = '' -- e70f
|
FileFormat.icon = {
|
||||||
local icon_mac = '' -- e711
|
unix = '', -- e712
|
||||||
return function()
|
dos = '', -- e70f
|
||||||
if options.icons_enabled and not options.icon then
|
mac = '' -- e711
|
||||||
|
}
|
||||||
|
|
||||||
|
FileFormat.update_status = function(self)
|
||||||
|
if self.options.icons_enabled and not self.options.icon then
|
||||||
local format = vim.bo.fileformat
|
local format = vim.bo.fileformat
|
||||||
if format == 'unix' then
|
return FileFormat.icon[format] or format
|
||||||
return icon_linux
|
|
||||||
elseif format == 'dos' then
|
|
||||||
return icon_windos
|
|
||||||
elseif format == 'mac' then
|
|
||||||
return icon_mac
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return vim.bo.fileformat
|
return vim.bo.fileformat
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
return {init = function(options) return fileformat(options) end}
|
return FileFormat
|
||||||
|
|
|
@ -1,27 +1,39 @@
|
||||||
-- Copyright (c) 2020-2021 shadmansaleh
|
-- Copyright (c) 2020-2021 shadmansaleh
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
local function filename(options)
|
local FileName = require('lualine.component'):new()
|
||||||
-- setting defaults
|
|
||||||
if options.file_status == nil then options.file_status = true end
|
|
||||||
if options.shorten == nil then options.shorten = true end
|
|
||||||
if options.full_path == nil then options.full_path = false end
|
|
||||||
|
|
||||||
return function()
|
FileName.new = function(self, options, child)
|
||||||
local data
|
local new_instence = self._parent:new(options, child or FileName)
|
||||||
if not options.full_path then
|
|
||||||
data = vim.fn.expand('%:t')
|
-- setting defaults
|
||||||
elseif options.shorten then
|
if new_instence.options.file_status == nil then
|
||||||
data = vim.fn.expand('%:~:.')
|
new_instence.options.file_status = true
|
||||||
else
|
|
||||||
data = vim.fn.expand('%:p')
|
|
||||||
end
|
end
|
||||||
|
if new_instence.options.shorten == nil then
|
||||||
|
new_instence.options.shorten = true
|
||||||
|
end
|
||||||
|
if new_instence.options.full_path == nil then
|
||||||
|
new_instence.options.full_path = false
|
||||||
|
end
|
||||||
|
|
||||||
|
return new_instence
|
||||||
|
end
|
||||||
|
|
||||||
|
FileName.update_status = function(self)
|
||||||
|
local data = vim.fn.expand('%:p')
|
||||||
|
if not self.options.full_path then
|
||||||
|
data = vim.fn.expand('%:t')
|
||||||
|
elseif self.options.shorten then
|
||||||
|
data = vim.fn.expand('%:~:.')
|
||||||
|
end
|
||||||
|
|
||||||
if data == '' then
|
if data == '' then
|
||||||
data = '[No Name]'
|
data = '[No Name]'
|
||||||
elseif vim.fn.winwidth(0) <= 84 or #data > 40 then
|
elseif vim.fn.winwidth(0) <= 84 or #data > 40 then
|
||||||
data = vim.fn.pathshorten(data)
|
data = vim.fn.pathshorten(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
if options.file_status then
|
if self.options.file_status then
|
||||||
if vim.bo.modified then
|
if vim.bo.modified then
|
||||||
data = data .. '[+]'
|
data = data .. '[+]'
|
||||||
elseif vim.bo.modifiable == false or vim.bo.readonly == true then
|
elseif vim.bo.modifiable == false or vim.bo.readonly == true then
|
||||||
|
@ -30,6 +42,5 @@ local function filename(options)
|
||||||
end
|
end
|
||||||
return data
|
return data
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
return {init = function(options) return filename(options) end}
|
return FileName
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
-- Copyright (c) 2020-2021 hoob3rt
|
-- Copyright (c) 2020-2021 hoob3rt
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
local function filetype(options)
|
local FileType = require('lualine.component'):new()
|
||||||
return function()
|
|
||||||
|
FileType.update_status = function(self)
|
||||||
local data = vim.bo.filetype
|
local data = vim.bo.filetype
|
||||||
if #data > 0 then
|
if #data > 0 then
|
||||||
local ok, devicons = pcall(require, 'nvim-web-devicons')
|
local ok, devicons = pcall(require, 'nvim-web-devicons')
|
||||||
if ok then
|
if ok then
|
||||||
local f_name, f_extension = vim.fn.expand('%:t'), vim.fn.expand('%:e')
|
local f_name, f_extension = vim.fn.expand('%:t'), vim.fn.expand('%:e')
|
||||||
options.icon = devicons.get_icon(f_name, f_extension)
|
self.options.icon = devicons.get_icon(f_name, f_extension)
|
||||||
else
|
else
|
||||||
ok = vim.fn.exists('*WebDevIconsGetFileTypeSymbol')
|
ok = vim.fn.exists('*WebDevIconsGetFileTypeSymbol')
|
||||||
if ok ~= 0 then
|
if ok ~= 0 then
|
||||||
options.icon = vim.fn.WebDevIconsGetFileTypeSymbol()
|
self.options.icon = vim.fn.WebDevIconsGetFileTypeSymbol()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return data
|
return data
|
||||||
end
|
end
|
||||||
return ''
|
return ''
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
return {init = function(options) return filetype(options) end}
|
return FileType
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
-- Copyright (c) 2020-2021 hoob3rt
|
-- Copyright (c) 2020-2021 hoob3rt
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
local function hostname()
|
local HostName = require('lualine.component'):new()
|
||||||
local data = vim.loop.os_gethostname()
|
|
||||||
return data
|
|
||||||
end
|
|
||||||
|
|
||||||
return hostname
|
HostName.update_status = vim.loop.os_gethostname()
|
||||||
|
|
||||||
|
return HostName
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
-- Copyright (c) 2020-2021 hoob3rt
|
-- Copyright (c) 2020-2021 hoob3rt
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
local function location()
|
local Location = require('lualine.component'):new()
|
||||||
local data = [[%3l:%-2c]]
|
|
||||||
return data
|
|
||||||
end
|
|
||||||
|
|
||||||
return location
|
Location.update_status = function() return [[%3l:%-2c]] end
|
||||||
|
|
||||||
|
return Location
|
||||||
|
|
|
@ -1,42 +1,8 @@
|
||||||
-- Copyright (c) 2020-2021 hoob3rt
|
-- Copyright (c) 2020-2021 hoob3rt
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
-- LuaFormatter off
|
local Mode = require('lualine.component'):new()
|
||||||
local mode_map = {
|
local get_mode = require('lualine.utils.mode').get_mode
|
||||||
['n'] = 'NORMAL',
|
|
||||||
['no'] = 'O-PENDING',
|
|
||||||
['nov'] = 'O-PENDING',
|
|
||||||
['noV'] = 'O-PENDING',
|
|
||||||
['no'] = 'O-PENDING',
|
|
||||||
['niI'] = 'NORMAL',
|
|
||||||
['niR'] = 'NORMAL',
|
|
||||||
['niV'] = 'NORMAL',
|
|
||||||
['v'] = 'VISUAL',
|
|
||||||
['V'] = 'V-LINE',
|
|
||||||
[''] = 'V-BLOCK',
|
|
||||||
['s'] = 'SELECT',
|
|
||||||
['S'] = 'S-LINE',
|
|
||||||
[''] = 'S-BLOCK',
|
|
||||||
['i'] = 'INSERT',
|
|
||||||
['ic'] = 'INSERT',
|
|
||||||
['ix'] = 'INSERT',
|
|
||||||
['R'] = 'REPLACE',
|
|
||||||
['Rc'] = 'REPLACE',
|
|
||||||
['Rv'] = 'V-REPLACE',
|
|
||||||
['Rx'] = 'REPLACE',
|
|
||||||
['c'] = 'COMMAND',
|
|
||||||
['cv'] = 'EX',
|
|
||||||
['ce'] = 'EX',
|
|
||||||
['r'] = 'REPLACE',
|
|
||||||
['rm'] = 'MORE',
|
|
||||||
['r?'] = 'CONFIRM',
|
|
||||||
['!'] = 'SHELL',
|
|
||||||
['t'] = 'TERMINAL',
|
|
||||||
}
|
|
||||||
-- LuaFormatter on
|
|
||||||
local function mode()
|
|
||||||
local mode_code = vim.api.nvim_get_mode().mode
|
|
||||||
if mode_map[mode_code] == nil then return mode_code end
|
|
||||||
return mode_map[mode_code]
|
|
||||||
end
|
|
||||||
|
|
||||||
return mode
|
Mode.update_status = get_mode
|
||||||
|
|
||||||
|
return Mode
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
-- Copyright (c) 2020-2021 hoob3rt
|
-- Copyright (c) 2020-2021 hoob3rt
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
local function progress()
|
local Progress = require('lualine.component'):new()
|
||||||
local data = [[%3P]]
|
|
||||||
return data
|
|
||||||
end
|
|
||||||
|
|
||||||
return progress
|
Progress.update_status = function() return [[%3P]] end
|
||||||
|
|
||||||
|
return Progress
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
local EvalFuncComponent = require('lualine.component'):new()
|
||||||
|
|
||||||
|
EvalFuncComponent.update_status = function(self)
|
||||||
|
local component = self.options[1]
|
||||||
|
local ok, status = EvalFuncComponent.evallua(component)
|
||||||
|
if not ok then status = EvalFuncComponent.vim_function(component) end
|
||||||
|
return status
|
||||||
|
end
|
||||||
|
|
||||||
|
EvalFuncComponent.evallua = function(code)
|
||||||
|
if loadstring(string.format('return %s ~= nil', code)) and
|
||||||
|
loadstring(string.format([[return %s ~= nil]], code))() then
|
||||||
|
-- lua veriable component
|
||||||
|
return true, loadstring(string.format(
|
||||||
|
[[
|
||||||
|
local ok, return_val = pcall(tostring, %s)
|
||||||
|
if ok then return return_val end
|
||||||
|
return '']], code))()
|
||||||
|
end
|
||||||
|
return false, ''
|
||||||
|
end
|
||||||
|
|
||||||
|
EvalFuncComponent.vim_function = function(name)
|
||||||
|
-- vim function component
|
||||||
|
local ok, return_val = pcall(vim.fn[name])
|
||||||
|
if not ok then return '' end -- function call failed
|
||||||
|
ok, return_val = pcall(tostring, return_val)
|
||||||
|
if ok then
|
||||||
|
return return_val
|
||||||
|
else
|
||||||
|
return ''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return EvalFuncComponent
|
|
@ -0,0 +1,9 @@
|
||||||
|
local FunctionComponent = require('lualine.component'):new()
|
||||||
|
|
||||||
|
FunctionComponent.new = function(self, options, child)
|
||||||
|
local new_instence = self._parent:new(options, child or FunctionComponent)
|
||||||
|
new_instence.update_status = options[1]
|
||||||
|
return new_instence
|
||||||
|
end
|
||||||
|
|
||||||
|
return FunctionComponent
|
|
@ -0,0 +1,19 @@
|
||||||
|
local VarComponent = require('lualine.component'):new()
|
||||||
|
VarComponent.update_status = function(self)
|
||||||
|
local component = self.options[1]
|
||||||
|
-- vim veriable component
|
||||||
|
-- accepts g:, v:, t:, w:, b:, o, go:, vo:, to:, wo:, bo:
|
||||||
|
-- filters g portion from g:var
|
||||||
|
local scope = component:match('[gvtwb]?o?')
|
||||||
|
-- filters var portion from g:var
|
||||||
|
local var_name = component:sub(#scope + 2, #component)
|
||||||
|
-- Displays nothing when veriable aren't present
|
||||||
|
local return_val = vim[scope][var_name]
|
||||||
|
if return_val == nil then return '' end
|
||||||
|
local ok
|
||||||
|
ok, return_val = pcall(tostring, return_val)
|
||||||
|
if ok then return return_val end
|
||||||
|
return ''
|
||||||
|
end
|
||||||
|
|
||||||
|
return VarComponent
|
|
@ -42,7 +42,7 @@ end
|
||||||
-- @param highlight_group:(string) name of highlight group
|
-- @param highlight_group:(string) name of highlight group
|
||||||
-- @return: (string) highlight group name with mode
|
-- @return: (string) highlight group name with mode
|
||||||
local function append_mode(highlight_group)
|
local function append_mode(highlight_group)
|
||||||
local mode = require('lualine.components.mode')()
|
local mode = require('lualine.utils.mode').get_mode()
|
||||||
if mode == 'VISUAL' or mode == 'V-BLOCK' or mode == 'V-LINE' or mode ==
|
if mode == 'VISUAL' or mode == 'V-BLOCK' or mode == 'V-LINE' or mode ==
|
||||||
'SELECT' or mode == 'S-LINE' or mode == 'S-BLOCK' then
|
'SELECT' or mode == 'S-LINE' or mode == 'S-BLOCK' then
|
||||||
highlight_group = highlight_group .. '_visual'
|
highlight_group = highlight_group .. '_visual'
|
||||||
|
@ -159,7 +159,7 @@ function M.get_transitional_highlights(left_section_data, right_section_data,
|
||||||
-- Grab the last highlighter of left section
|
-- Grab the last highlighter of left section
|
||||||
if left_section_data then
|
if left_section_data then
|
||||||
-- extract highlight_name from .....%#highlight_name#
|
-- extract highlight_name from .....%#highlight_name#
|
||||||
left_highlight_name = left_section_data:match('.*%%#(.*)#')
|
left_highlight_name = left_section_data:match('.*%%#(.-)#')
|
||||||
else
|
else
|
||||||
-- When right section us unavailable default to lualine_c
|
-- When right section us unavailable default to lualine_c
|
||||||
left_highlight_name = append_mode('lualine_c')
|
left_highlight_name = append_mode('lualine_c')
|
||||||
|
@ -168,10 +168,8 @@ function M.get_transitional_highlights(left_section_data, right_section_data,
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if right_section_data then
|
if right_section_data then
|
||||||
-- using vim-regex cause lua-paterns don't have non-greedy matching
|
|
||||||
-- extract highlight_name from %#highlight_name#....
|
-- extract highlight_name from %#highlight_name#....
|
||||||
right_highlight_name = vim.fn.matchlist(right_section_data,
|
right_highlight_name = right_section_data:match('%%#(.-)#.*')
|
||||||
[[%#\(.\{-\}\)#]])[2]
|
|
||||||
else
|
else
|
||||||
-- When right section us unavailable default to lualine_c
|
-- When right section us unavailable default to lualine_c
|
||||||
right_highlight_name = append_mode('lualine_c')
|
right_highlight_name = append_mode('lualine_c')
|
||||||
|
|
|
@ -57,70 +57,25 @@ local function check_single_separator()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function load_special_components(component)
|
|
||||||
return function()
|
|
||||||
-- precedence lualine_component > vim_var > lua_var > vim_function
|
|
||||||
if component:find('[gvtwb]?o?:') == 1 then
|
|
||||||
-- vim veriable component
|
|
||||||
-- accepts g:, v:, t:, w:, b:, o, go:, vo:, to:, wo:, bo:
|
|
||||||
-- filters g portion from g:var
|
|
||||||
local scope = component:match('[gvtwb]?o?')
|
|
||||||
-- filters var portion from g:var
|
|
||||||
local var_name = component:sub(#scope + 2, #component)
|
|
||||||
-- Displays nothing when veriable aren't present
|
|
||||||
local return_val = vim[scope][var_name]
|
|
||||||
if return_val == nil then return '' end
|
|
||||||
local ok
|
|
||||||
ok, return_val = pcall(tostring, return_val)
|
|
||||||
if ok then return return_val end
|
|
||||||
return ''
|
|
||||||
elseif loadstring(string.format('return %s ~= nil', component)) and
|
|
||||||
loadstring(string.format([[return %s ~= nil]], component))() then
|
|
||||||
-- lua veriable component
|
|
||||||
return loadstring(string.format([[
|
|
||||||
local ok, return_val = pcall(tostring, %s)
|
|
||||||
if ok then return return_val end
|
|
||||||
return '']], component))()
|
|
||||||
else
|
|
||||||
-- vim function component
|
|
||||||
local ok, return_val = pcall(vim.fn[component])
|
|
||||||
if not ok then return '' end -- function call failed
|
|
||||||
ok, return_val = pcall(tostring, return_val)
|
|
||||||
if ok then
|
|
||||||
return return_val
|
|
||||||
else
|
|
||||||
return ''
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function component_loader(component)
|
local function component_loader(component)
|
||||||
if type(component[1]) == 'function' then return component end
|
if type(component[1]) == 'function' then
|
||||||
|
return require 'lualine.components.special.functon_component':new(component)
|
||||||
|
end
|
||||||
if type(component[1]) == 'string' then
|
if type(component[1]) == 'string' then
|
||||||
-- Keep component name for later use as component[1] will be overwritten
|
|
||||||
-- With component function
|
|
||||||
component.component_name = component[1]
|
|
||||||
-- apply default args
|
|
||||||
for opt_name, opt_val in pairs(config.options) do
|
|
||||||
if component[opt_name] == nil then component[opt_name] = opt_val end
|
|
||||||
end
|
|
||||||
-- load the component
|
-- load the component
|
||||||
local ok, loaded_component = pcall(require, 'lualine.components.' ..
|
local ok, loaded_component = pcall(require,
|
||||||
component.component_name)
|
'lualine.components.' .. component[1])
|
||||||
if not ok then
|
if ok then
|
||||||
loaded_component = load_special_components(component.component_name)
|
component.component_name = component[1]
|
||||||
end
|
loaded_component = loaded_component:new(component)
|
||||||
component[1] = loaded_component
|
elseif component[1]:find('[gvtwb]?o?:') == 1 then
|
||||||
if type(component[1]) == 'table' then
|
loaded_component =
|
||||||
component[1] = component[1].init(component)
|
require 'lualine.components.special.vim_var_component':new(component)
|
||||||
end
|
else
|
||||||
-- set custom highlights
|
loaded_component =
|
||||||
if component.color then
|
require 'lualine.components.special.eval_func_component':new(component)
|
||||||
component.color_highlight = highlight.create_component_highlight_group(
|
|
||||||
component.color, component.component_name,
|
|
||||||
component)
|
|
||||||
end
|
end
|
||||||
|
return loaded_component
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -132,8 +87,9 @@ local function load_sections(sections)
|
||||||
end
|
end
|
||||||
component.self = {}
|
component.self = {}
|
||||||
component.self.section = section_name
|
component.self.section = section_name
|
||||||
component_loader(component)
|
-- apply default args
|
||||||
section[index] = component
|
component = vim.tbl_extend('keep', component, config.options)
|
||||||
|
section[index] = component_loader(component)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
-- Copyright (c) 2020-2021 shadmansaleh
|
|
||||||
-- MIT license, see LICENSE for more details.
|
|
||||||
local M = {}
|
|
||||||
|
|
||||||
local highlight = require 'lualine.highlight'
|
|
||||||
|
|
||||||
-- set upper or lower case
|
|
||||||
function M.apply_case(status, options)
|
|
||||||
-- Donn't work on components that emit vim statusline escaped chars
|
|
||||||
if status:find('%%') and not status:find('%%%%') then return status end
|
|
||||||
if options.upper == true then
|
|
||||||
return status:upper()
|
|
||||||
elseif options.lower == true then
|
|
||||||
return status:lower()
|
|
||||||
end
|
|
||||||
return status
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Adds spaces to left and right of a component
|
|
||||||
function M.apply_padding(status, options)
|
|
||||||
local l_padding = (options.left_padding or options.padding or 1)
|
|
||||||
local r_padding = (options.right_padding or options.padding or 1)
|
|
||||||
if l_padding then
|
|
||||||
if 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(status, [[\(%#.\{-\}#\)]])[2]
|
|
||||||
status = pre_highlight .. string.rep(' ', l_padding) ..
|
|
||||||
status:sub(#pre_highlight + 1, #status)
|
|
||||||
else
|
|
||||||
status = string.rep(' ', l_padding) .. status
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if r_padding then status = status .. string.rep(' ', r_padding) end
|
|
||||||
return status
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Applies custom highlights for component
|
|
||||||
function M.apply_highlights(status, options, default_hl)
|
|
||||||
if options.color_highlight then
|
|
||||||
status = highlight.component_format_highlight(options.color_highlight) ..
|
|
||||||
status
|
|
||||||
end
|
|
||||||
return status .. default_hl
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Apply icon in front of component
|
|
||||||
function M.apply_icon(status, options)
|
|
||||||
if options.icons_enabled and options.icon then
|
|
||||||
status = options.icon .. ' ' .. status
|
|
||||||
end
|
|
||||||
return status
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Apply separator at end of component only when
|
|
||||||
-- custom highlights haven't affected background
|
|
||||||
function M.apply_spearator(status, options)
|
|
||||||
local separator
|
|
||||||
if options.separator and #options.separator > 0 then
|
|
||||||
separator = options.separator
|
|
||||||
elseif options.component_separators then
|
|
||||||
if options.self.section < 'lualine_x' then
|
|
||||||
separator = options.component_separators[1]
|
|
||||||
else
|
|
||||||
separator = options.component_separators[2]
|
|
||||||
end
|
|
||||||
options.separator = separator
|
|
||||||
end
|
|
||||||
if separator then status = status .. separator end
|
|
||||||
options.separator_applied = separator
|
|
||||||
return status
|
|
||||||
end
|
|
||||||
|
|
||||||
function M.strip_separator(status, options)
|
|
||||||
if options.separator_applied then
|
|
||||||
status = status:sub(1, #status - #options.separator_applied)
|
|
||||||
options.separator_applied = nil
|
|
||||||
end
|
|
||||||
return status
|
|
||||||
end
|
|
||||||
|
|
||||||
return M
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
-- Copyright (c) 2020-2021 hoob3rt
|
||||||
|
-- MIT license, see LICENSE for more details.
|
||||||
|
-- LuaFormatter off
|
||||||
|
|
||||||
|
local Mode = {}
|
||||||
|
|
||||||
|
Mode.map = {
|
||||||
|
['n'] = 'NORMAL',
|
||||||
|
['no'] = 'O-PENDING',
|
||||||
|
['nov'] = 'O-PENDING',
|
||||||
|
['noV'] = 'O-PENDING',
|
||||||
|
['no'] = 'O-PENDING',
|
||||||
|
['niI'] = 'NORMAL',
|
||||||
|
['niR'] = 'NORMAL',
|
||||||
|
['niV'] = 'NORMAL',
|
||||||
|
['v'] = 'VISUAL',
|
||||||
|
['V'] = 'V-LINE',
|
||||||
|
[''] = 'V-BLOCK',
|
||||||
|
['s'] = 'SELECT',
|
||||||
|
['S'] = 'S-LINE',
|
||||||
|
[''] = 'S-BLOCK',
|
||||||
|
['i'] = 'INSERT',
|
||||||
|
['ic'] = 'INSERT',
|
||||||
|
['ix'] = 'INSERT',
|
||||||
|
['R'] = 'REPLACE',
|
||||||
|
['Rc'] = 'REPLACE',
|
||||||
|
['Rv'] = 'V-REPLACE',
|
||||||
|
['Rx'] = 'REPLACE',
|
||||||
|
['c'] = 'COMMAND',
|
||||||
|
['cv'] = 'EX',
|
||||||
|
['ce'] = 'EX',
|
||||||
|
['r'] = 'REPLACE',
|
||||||
|
['rm'] = 'MORE',
|
||||||
|
['r?'] = 'CONFIRM',
|
||||||
|
['!'] = 'SHELL',
|
||||||
|
['t'] = 'TERMINAL',
|
||||||
|
}
|
||||||
|
-- LuaFormatter on
|
||||||
|
function Mode.get_mode()
|
||||||
|
local mode_code = vim.api.nvim_get_mode().mode
|
||||||
|
if Mode.map[mode_code] == nil then return mode_code end
|
||||||
|
return Mode.map[mode_code]
|
||||||
|
end
|
||||||
|
|
||||||
|
return Mode
|
|
@ -1,52 +1,49 @@
|
||||||
-- Copyright (c) 2020-2021 hoob3rt
|
-- Copyright (c) 2020-2021 hoob3rt
|
||||||
-- MIT license, see LICENSE for more details.
|
-- MIT license, see LICENSE for more details.
|
||||||
local utils_component = require('lualine.utils.component')
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
local utils = require('lualine.utils.utils')
|
||||||
-- Returns formated string for a section
|
-- Returns formated string for a section
|
||||||
function M.draw_section(section, highlight_name)
|
function M.draw_section(section, highlight_name)
|
||||||
local status = {}
|
local status = {}
|
||||||
local drawn_components = {}
|
|
||||||
for _, component in pairs(section) do
|
for _, component in pairs(section) do
|
||||||
local localstatus = component[1]()
|
-- load components into status table
|
||||||
if #localstatus > 0 then
|
table.insert(status, component:draw(highlight_name))
|
||||||
local custom_highlight_at_begining =
|
end
|
||||||
localstatus:find('%%#.*#') == 1 or component.color ~= nil
|
|
||||||
-- Apply modifier functions for options
|
-- Flags required for knowing when to remove component separator
|
||||||
if component.format then localstatus = component.format(localstatus) end
|
local next_component_colored = false
|
||||||
localstatus = utils_component.apply_icon(localstatus, component)
|
local last_component_found = false
|
||||||
localstatus = utils_component.apply_case(localstatus, component)
|
|
||||||
localstatus = utils_component.apply_padding(localstatus, component)
|
-- Check through components to see when component separator need to be removed
|
||||||
localstatus = utils_component.apply_highlights(localstatus, component,
|
for component_no = #section, 1, -1 do
|
||||||
|
-- Remove component separator with highlight for last component
|
||||||
|
if not last_component_found and #status[component_no] > 0 then
|
||||||
|
last_component_found = true
|
||||||
|
status[component_no] = section[component_no]:strip_separator(
|
||||||
highlight_name)
|
highlight_name)
|
||||||
localstatus = utils_component.apply_spearator(localstatus, component)
|
end
|
||||||
if custom_highlight_at_begining or (#drawn_components > 0 and
|
-- Remove component separator when color option is used in next component
|
||||||
not drawn_components[#drawn_components].separator_applied) then
|
if next_component_colored then
|
||||||
|
next_component_colored = false
|
||||||
|
status[component_no] = section[component_no]:strip_separator()
|
||||||
|
end
|
||||||
|
-- Remove component separator when color option is used to color background
|
||||||
|
if section[component_no].options.color and
|
||||||
|
section[component_no].options.color.bg then
|
||||||
|
next_component_colored = true
|
||||||
|
status[component_no] = section[component_no]:strip_separator()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove empty strings from status
|
||||||
|
status = utils.list_shrink(status)
|
||||||
|
local status_str = table.concat(status)
|
||||||
|
if status_str:find('%%#.*#') == 1 then
|
||||||
-- Don't prepend with old highlight when the component changes it imidiately
|
-- Don't prepend with old highlight when the component changes it imidiately
|
||||||
-- Or when it was already applied with separator
|
return status_str
|
||||||
table.insert(status, localstatus)
|
|
||||||
else
|
else
|
||||||
table.insert(status, highlight_name .. localstatus)
|
return highlight_name .. status_str
|
||||||
end
|
end
|
||||||
table.insert(drawn_components, component)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- Draw nothing when all the components were empty
|
|
||||||
if #status == 0 then return '' end
|
|
||||||
-- Remove separators sorounding custom highlighted component
|
|
||||||
for i = 1, #status do
|
|
||||||
if (drawn_components[i].color and drawn_components[i].color.bg) or
|
|
||||||
drawn_components[i].custom_highlight then
|
|
||||||
status[i] =
|
|
||||||
utils_component.strip_separator(status[i], drawn_components[i])
|
|
||||||
if i > 1 then
|
|
||||||
status[i - 1] = utils_component.strip_separator(status[i - 1],
|
|
||||||
drawn_components[i - 1])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
status[#status] = utils_component.strip_separator(status[#status],
|
|
||||||
drawn_components[#status])
|
|
||||||
return table.concat(status)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|
|
@ -54,4 +54,13 @@ function M.clear_highlights()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- remove empty strings from list
|
||||||
|
function M.list_shrink(list)
|
||||||
|
local new_list = {}
|
||||||
|
for i = 1, #list do
|
||||||
|
if list[i] and #list[i] > 0 then table.insert(new_list, list[i]) end
|
||||||
|
end
|
||||||
|
return new_list
|
||||||
|
end
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|
Loading…
Reference in New Issue