1

Regenerate nvim config

This commit is contained in:
2024-06-02 03:29:20 +02:00
parent 75eea0c030
commit ef2e28883d
5576 changed files with 604886 additions and 503 deletions

View File

@ -0,0 +1,656 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local M = {}
local lualine_require = require('lualine_require')
local modules = lualine_require.lazy_require {
highlight = 'lualine.highlight',
loader = 'lualine.utils.loader',
utils_section = 'lualine.utils.section',
utils = 'lualine.utils.utils',
utils_notices = 'lualine.utils.notices',
config_module = 'lualine.config',
nvim_opts = 'lualine.utils.nvim_opts',
}
local config -- Stores currently applied config
local timers = {
stl_timer = vim.loop.new_timer(),
tal_timer = vim.loop.new_timer(),
wb_timer = vim.loop.new_timer(),
halt_stl_refresh = false, -- mutex ?
halt_tal_refresh = false,
halt_wb_refresh = false,
}
local last_focus = {}
local refresh_real_curwin
-- The events on which lualine redraws itself
local default_refresh_events =
'WinEnter,BufEnter,BufWritePost,SessionLoadPost,FileChangedShellPost,VimResized,Filetype,CursorMoved,CursorMovedI,ModeChanged'
-- Helper for apply_transitional_separators()
--- finds first applied highlight group after str_checked in status
---@param status string : unprocessed statusline string
---@param str_checked number : position of how far status has been checked
---@return string|nil the hl group name or nil
local function find_next_hl(status, str_checked)
-- Gets the next valid hl group from str_checked
local hl_pos_start, hl_pos_end = status:find('%%#.-#', str_checked)
while true do
if not hl_pos_start then
return nil
end
-- When there are more that one hl group next to one another like
-- %#HL1#%#HL2#%#HL3# we need to return HL3. This makes that happen.
local next_start, next_end = status:find('^%%#.-#', hl_pos_end + 1)
if next_start == nil then
break
end
hl_pos_start, hl_pos_end = next_start, next_end
end
return status:sub(hl_pos_start + 2, hl_pos_end - 1)
end
-- Helper for apply_transitional_separators()
--- applies transitional separator highlight + transitional separator
---@param status string : unprocessed statusline string
---@param str_checked number : position of how far status has been checked
---@param last_hl string : last applied hl group name before str_checked
---@param reverse boolean : reverse the hl group ( true for right separators )
---@return string|nil concatenate separator highlight and transitional separator
local function fill_section_separator(status, is_focused, str_checked, last_hl, sep, reverse)
-- Inserts transitional separator along with transitional highlight
local next_hl = find_next_hl(status, str_checked)
if last_hl == nil then
last_hl = modules.highlight.get_stl_default_hl(is_focused)
end
if next_hl == nil then
next_hl = modules.highlight.get_stl_default_hl(is_focused)
end
if #next_hl == 0 or #last_hl == 0 then
return
end
local transitional_highlight = reverse -- lua ternary assignment x ? y : z
and modules.highlight.get_transitional_highlights(last_hl, next_hl)
or modules.highlight.get_transitional_highlights(next_hl, last_hl)
if transitional_highlight then
return transitional_highlight .. sep
end
end
--- processes statusline string
--- replaces %z/Z{sep} with proper left/right separator highlight + sep
---@param status string : unprocessed statusline string
---@return string : processed statusline string
local function apply_transitional_separators(status, is_focused)
local status_applied = {} -- Collects all the pieces for concatenation
local last_hl -- Stores last highlight group that we found
local last_hl_reseted = false -- Whether last_hl is nil after reset
-- it after %=
local copied_pos = 1 -- Tracks how much we've copied over to status_applied
local str_checked = 1 -- Tracks where the searcher head is at
-- Process entire status replace the %z{sep} & %Z{sep} placeholders
-- with proper transitional separator.
while str_checked ~= nil do
str_checked = status:find('%%', str_checked)
if str_checked == nil then
break
end
table.insert(status_applied, status:sub(copied_pos, str_checked - 1))
-- -1 so we don't copy '%'
copied_pos = str_checked
local next_char = modules.utils.charAt(status, str_checked + 1)
if next_char == '#' then
-- %#hl_name# highlights
last_hl = status:match('^%%#(.-)#', str_checked)
str_checked = str_checked + #last_hl + 3
elseif next_char == 'z' then
-- %z{sep} is marker for left separator and
local sep = status:match('^%%z{(.-)}', str_checked)
str_checked = str_checked + #sep + 4 -- 4 = len(%{})
if not (last_hl == nil and last_hl_reseted) then
local trans_sep = fill_section_separator(status, is_focused, str_checked, last_hl, sep, false)
if trans_sep then
table.insert(status_applied, trans_sep)
end
end
if last_hl_reseted then
last_hl_reseted = false
end
copied_pos = str_checked
elseif next_char == 'Z' then
-- %Z{sep} is marker for right separator and
local sep = status:match('^%%Z{(.-)}', str_checked)
str_checked = str_checked + #sep + 4 -- 4 = len(%{})
if status:find('^%%z', str_checked) or status:find('^%%<%%Z', str_checked) then
-- When transitional right_sep and left_sep are right next to each other
-- and in this exact order skip the left sep as we can't draw both.
str_checked = status:find('}', str_checked) + 1
end
local trans_sep = fill_section_separator(status, is_focused, str_checked, last_hl, sep, true)
if trans_sep then
table.insert(status_applied, trans_sep)
end
copied_pos = str_checked
elseif next_char == '%' then
str_checked = str_checked + 2 -- Skip the following % too
elseif next_char == '=' and last_hl and (last_hl:find('^lualine_a') or last_hl:find('^lualine_b')) then
-- TODO: Fix this properly
-- This check for lualine_a and lualine_b is dumb. It doesn't guarantee
-- c or x section isn't present. Worst case scenario after this patch
-- we have another visual bug that occurs less frequently.
-- Annoying Edge Cases
last_hl = nil
last_hl_reseted = true
str_checked = str_checked + 1 -- Skip the following % too
else
str_checked = str_checked + 1 -- Push it forward to avoid inf loop
end
end
table.insert(status_applied, status:sub(copied_pos)) -- Final chunk
return table.concat(status_applied)
end
--- creates the statusline string
---@param sections table : section config where components are replaced with
--- component objects
---@param is_focused boolean : whether being evaluated for focused window or not
---@return string statusline string
local statusline = modules.utils.retry_call_wrap(function(sections, is_focused, is_winbar)
-- The sequence sections should maintain [SECTION_SEQUENCE]
local section_sequence = { 'a', 'b', 'c', 'x', 'y', 'z' }
local status = {}
local applied_midsection_divider = false
local applied_trunc = false
for _, section_name in ipairs(section_sequence) do
if sections['lualine_' .. section_name] then
-- insert highlight+components of this section to status_builder
local section_data =
modules.utils_section.draw_section(sections['lualine_' .. section_name], section_name, is_focused)
if #section_data > 0 then
if not applied_midsection_divider and section_name > 'c' then
applied_midsection_divider = true
section_data = modules.highlight.format_highlight('c', is_focused) .. '%=' .. section_data
end
if not applied_trunc and section_name > 'b' then
applied_trunc = true
section_data = '%<' .. section_data
end
table.insert(status, section_data)
end
end
end
if applied_midsection_divider == false and config.options.always_divide_middle ~= false and not is_winbar then
-- When non of section x,y,z is present
table.insert(status, modules.highlight.format_highlight('c', is_focused) .. '%=')
end
return apply_transitional_separators(table.concat(status), is_focused)
end)
--- check if any extension matches the filetype and return proper sections
---@param current_ft string : filetype name of current file
---@param is_focused boolean : whether being evaluated for focused window or not
---@return table|nil : (section_table) section config where components are replaced with
--- component objects
-- TODO: change this so it uses a hash table instead of iteration over list
-- to improve redraws. Add buftype / bufname for extensions
-- or some kind of cond ?
local function get_extension_sections(current_ft, is_focused, sec_name)
for _, extension in ipairs(config.extensions) do
if vim.tbl_contains(extension.filetypes, current_ft) then
if is_focused then
return extension[sec_name]
else
return extension['inactive_' .. sec_name] or extension[sec_name]
end
end
end
return nil
end
---@return string statusline string for tabline
local function tabline()
return statusline(config.tabline, 3)
end
local function notify_theme_error(theme_name)
local message_template = theme_name ~= 'auto'
and [[
### options.theme
Theme `%s` not found, falling back to `auto`. Check if spelling is right.
]]
or [[
### options.theme
Theme `%s` failed, falling back to `gruvbox`.
This shouldn't happen.
Please report the issue at https://github.com/nvim-lualine/lualine.nvim/issues .
Also provide what colorscheme you're using.
]]
modules.utils_notices.add_notice(string.format(message_template, theme_name))
end
--- Sets up theme by defining hl groups and setting theme cache in 'highlight.lua'.
--- Uses 'options.theme' variable to apply the theme:
--- - If the value is a string, it'll load a theme of that name.
--- - If it's a table, it's directly used as the theme.
--- If loading the theme fails, this falls back to 'auto' theme.
--- If the 'auto' theme also fails, this falls back to 'gruvbox' theme.
--- Also sets up auto command to reload lualine on ColorScheme or background changes.
local function setup_theme()
local function get_theme_from_config()
local theme_name = config.options.theme
if type(theme_name) == 'string' then
local ok, theme = pcall(modules.loader.load_theme, theme_name)
if ok and theme then
return theme
end
elseif type(theme_name) == 'table' then
-- use the provided theme as-is
return config.options.theme
elseif type(theme_name) == 'function' then
-- call function and use returned (dynamic) theme as-is
return config.options.theme()
end
if theme_name ~= 'auto' then
notify_theme_error(theme_name)
local ok, theme = pcall(modules.loader.load_theme, 'auto')
if ok and theme then
return theme
end
end
notify_theme_error('auto')
return modules.loader.load_theme('gruvbox')
end
local theme = get_theme_from_config()
modules.highlight.create_highlight_groups(theme)
vim.cmd([[autocmd lualine ColorScheme * lua require'lualine'.setup()
autocmd lualine OptionSet background lua require'lualine'.setup()]])
end
---@alias StatusDispatchSecs
---| 'sections'
---| 'winbar'
--- generates lualine.statusline & lualine.winbar function
--- creates a closer that can draw sections of sec_name.
---@param sec_name StatusDispatchSecs
---@return function(focused:bool):string
local function status_dispatch(sec_name)
return function(focused)
local retval
local current_ft = refresh_real_curwin
and vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(refresh_real_curwin), 'filetype')
or vim.bo.filetype
local is_focused = focused ~= nil and focused or modules.utils.is_focused()
if
vim.tbl_contains(
config.options.disabled_filetypes[(sec_name == 'sections' and 'statusline' or sec_name)],
current_ft
)
then
-- disable on specific filetypes
return nil
end
local extension_sections = get_extension_sections(current_ft, is_focused, sec_name)
if extension_sections ~= nil then
retval = statusline(extension_sections, is_focused, sec_name == 'winbar')
else
retval = statusline(config[(is_focused and '' or 'inactive_') .. sec_name], is_focused, sec_name == 'winbar')
end
return retval
end
end
---@alias LualineRefreshOptsKind
---| 'all'
---| 'tabpage'
---| 'window'
---@alias LualineRefreshOptsPlace
---| 'statusline'
---| 'tabline'
---| 'winbar'
---@class LualineRefreshOpts
---@field scope LualineRefreshOptsKind
---@field place LualineRefreshOptsPlace[]
---@field trigger 'autocmd'|'autocmd_redired'|'timer'|'unknown'
--- Refresh contents of lualine
---@param opts LualineRefreshOpts
local function refresh(opts)
if opts == nil then
opts = {}
end
opts = vim.tbl_extend('keep', opts, {
scope = 'tabpage',
place = { 'statusline', 'winbar', 'tabline' },
trigger = 'unknown',
})
-- updating statusline in autocommands context seems to trigger 100 different bugs
-- lets just defer it to a timer context and update there
-- Since updating stl in command mode doesn't take effect
-- refresh ModeChanged command in autocmd context as exception.
-- workaround for
-- https://github.com/neovim/neovim/issues/15300
-- https://github.com/neovim/neovim/issues/19464
-- https://github.com/nvim-lualine/lualine.nvim/issues/753
-- https://github.com/nvim-lualine/lualine.nvim/issues/751
-- https://github.com/nvim-lualine/lualine.nvim/issues/755
-- https://github.com/neovim/neovim/issues/19472
-- https://github.com/nvim-lualine/lualine.nvim/issues/791
if
opts.trigger == 'autocmd'
and vim.v.event.new_mode ~= 'c'
-- scheduling in op-pending mode seems to call the callback forever.
-- so this is restricted in op-pending mode.
-- https://github.com/neovim/neovim/issues/22263
-- https://github.com/nvim-lualine/lualine.nvim/issues/967
-- note this breaks mode component while switching to op-pending mode
and not vim.tbl_contains({ 'no', 'nov', 'noV' }, vim.v.event.new_mode)
and not vim.tbl_contains({ 'no', 'nov', 'noV' }, vim.v.event.old_mode)
then
opts.trigger = 'autocmd_redired'
vim.schedule(function()
M.refresh(opts)
end)
return
end
local wins = {}
local old_actual_curwin = vim.g.actual_curwin
-- ignore focus on filetypes listed in options.ignore_focus
local curwin = vim.api.nvim_get_current_win()
local curtab = vim.api.nvim_get_current_tabpage()
if last_focus[curtab] == nil or not vim.api.nvim_win_is_valid(last_focus[curtab]) then
if
not vim.tbl_contains(
config.options.ignore_focus,
vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(curwin), 'filetype')
)
then
last_focus[curtab] = curwin
else
local tab_wins = vim.api.nvim_tabpage_list_wins(curtab)
if #tab_wins == 1 then
last_focus[curtab] = curwin
else
local focusable_win = curwin
for _, win in ipairs(tab_wins) do
if
not vim.tbl_contains(
config.options.ignore_focus,
vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(win), 'filetype')
)
then
focusable_win = win
break
end
end
last_focus[curtab] = focusable_win
end
end
else
if
not vim.tbl_contains(
config.options.ignore_focus,
vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(curwin), 'filetype')
)
then
last_focus[curtab] = curwin
end
end
vim.g.actual_curwin = last_focus[curtab]
-- gather which windows needs update
if opts.scope == 'all' then
if vim.tbl_contains(opts.place, 'statusline') or vim.tbl_contains(opts.place, 'winbar') then
wins = vim.tbl_filter(function(win)
return vim.fn.win_gettype(win) ~= 'popup'
end, vim.api.nvim_list_wins())
end
elseif opts.scope == 'tabpage' then
if vim.tbl_contains(opts.place, 'statusline') or vim.tbl_contains(opts.place, 'winbar') then
wins = vim.tbl_filter(function(win)
return vim.fn.win_gettype(win) ~= 'popup'
end, vim.api.nvim_tabpage_list_wins(0))
end
elseif opts.scope == 'window' then
wins = { curwin }
end
-- update them
if not timers.halt_stl_refresh and vim.tbl_contains(opts.place, 'statusline') then
for _, win in ipairs(wins) do
refresh_real_curwin = config.options.globalstatus and last_focus[curtab] or win
local set_win = config.options.globalstatus
and vim.fn.win_gettype(refresh_real_curwin) == 'popup'
and refresh_real_curwin
or win
local stl_cur = vim.api.nvim_win_call(refresh_real_curwin, M.statusline)
local stl_last = modules.nvim_opts.get_cache('statusline', { window = set_win })
if stl_cur or stl_last then
modules.nvim_opts.set('statusline', stl_cur, { window = set_win })
end
end
end
if not timers.halt_wb_refresh and vim.tbl_contains(opts.place, 'winbar') then
for _, win in ipairs(wins) do
refresh_real_curwin = win
if vim.api.nvim_win_get_height(win) > 1 then
local wbr_cur = vim.api.nvim_win_call(refresh_real_curwin, M.winbar)
local wbr_last = modules.nvim_opts.get_cache('winbar', { window = win })
if wbr_cur or wbr_last then
modules.nvim_opts.set('winbar', wbr_cur, { window = win })
end
end
end
end
if not timers.halt_tal_refresh and vim.tbl_contains(opts.place, 'tabline') then
refresh_real_curwin = curwin
local tbl_cur = vim.api.nvim_win_call(curwin, tabline)
local tbl_last = modules.nvim_opts.get_cache('tabline', { global = true })
if tbl_cur or tbl_last then
modules.nvim_opts.set('tabline', tbl_cur, { global = true })
end
end
vim.g.actual_curwin = old_actual_curwin
refresh_real_curwin = nil
end
--- Sets &tabline option to lualine
---@param hide boolean|nil if should hide tabline
local function set_tabline(hide)
vim.loop.timer_stop(timers.tal_timer)
timers.halt_tal_refresh = true
vim.cmd([[augroup lualine_tal_refresh | exe "autocmd!" | augroup END]])
if not hide and next(config.tabline) ~= nil then
vim.loop.timer_start(
timers.tal_timer,
0,
config.options.refresh.tabline,
modules.utils.timer_call(timers.tal_timer, 'lualine_tal_refresh', function()
refresh { kind = 'tabpage', place = { 'tabline' }, trigger = 'timer' }
end, 3, 'lualine: Failed to refresh tabline')
)
modules.utils.define_autocmd(
default_refresh_events,
'*',
"call v:lua.require'lualine'.refresh({'kind': 'tabpage', 'place': ['tabline'], 'trigger': 'autocmd'})",
'lualine_tal_refresh'
)
modules.nvim_opts.set('showtabline', 2, { global = true })
timers.halt_tal_refresh = false
else
modules.nvim_opts.restore('tabline', { global = true })
modules.nvim_opts.restore('showtabline', { global = true })
end
end
--- Sets &statusline option to lualine
--- adds auto command to redraw lualine on VimResized event
---@param hide boolean|nil if should hide statusline
local function set_statusline(hide)
vim.loop.timer_stop(timers.stl_timer)
timers.halt_stl_refresh = true
vim.cmd([[augroup lualine_stl_refresh | exe "autocmd!" | augroup END]])
if not hide and (next(config.sections) ~= nil or next(config.inactive_sections) ~= nil) then
if vim.go.statusline == '' then
modules.nvim_opts.set('statusline', '%#Normal#', { global = true })
end
if config.options.globalstatus then
modules.nvim_opts.set('laststatus', 3, { global = true })
vim.loop.timer_start(
timers.stl_timer,
0,
config.options.refresh.statusline,
modules.utils.timer_call(timers.stl_timer, 'lualine_stl_refresh', function()
refresh { kind = 'window', place = { 'statusline' }, trigger = 'timer' }
end, 3, 'lualine: Failed to refresh statusline')
)
modules.utils.define_autocmd(
default_refresh_events,
'*',
"call v:lua.require'lualine'.refresh({'kind': 'window', 'place': ['statusline'], 'trigger': 'autocmd'})",
'lualine_stl_refresh'
)
else
modules.nvim_opts.set('laststatus', 2, { global = true })
vim.loop.timer_start(
timers.stl_timer,
0,
config.options.refresh.statusline,
modules.utils.timer_call(timers.stl_timer, 'lualine_stl_refresh', function()
refresh { kind = 'tabpage', place = { 'statusline' }, trigger = 'timer' }
end, 3, 'lualine: Failed to refresh statusline')
)
modules.utils.define_autocmd(
default_refresh_events,
'*',
"call v:lua.require'lualine'.refresh({'kind': 'tabpage', 'place': ['statusline'], 'trigger': 'autocmd'})",
'lualine_stl_refresh'
)
end
timers.halt_stl_refresh = false
else
modules.nvim_opts.restore('statusline', { global = true })
for _, win in ipairs(vim.api.nvim_list_wins()) do
modules.nvim_opts.restore('statusline', { window = win })
end
modules.nvim_opts.restore('laststatus', { global = true })
end
end
--- Sets &winbar option to lualine
---@param hide boolean|nil if should unset winbar
local function set_winbar(hide)
vim.loop.timer_stop(timers.wb_timer)
timers.halt_wb_refresh = true
vim.cmd([[augroup lualine_wb_refresh | exe "autocmd!" | augroup END]])
if not hide and (next(config.winbar) ~= nil or next(config.inactive_winbar) ~= nil) then
vim.loop.timer_start(
timers.wb_timer,
0,
config.options.refresh.winbar,
modules.utils.timer_call(timers.wb_timer, 'lualine_wb_refresh', function()
refresh { kind = 'tabpage', place = { 'winbar' }, trigger = 'timer' }
end, 3, 'lualine: Failed to refresh winbar')
)
modules.utils.define_autocmd(
default_refresh_events,
'*',
"call v:lua.require'lualine'.refresh({'kind': 'tabpage', 'place': ['winbar'], 'trigger': 'autocmd'})",
'lualine_wb_refresh'
)
timers.halt_wb_refresh = false
elseif vim.fn.has('nvim-0.8') == 1 then
modules.nvim_opts.restore('winbar', { global = true })
for _, win in ipairs(vim.api.nvim_list_wins()) do
modules.nvim_opts.restore('winbar', { window = win })
end
end
end
---@alias LualineHideOptsPlace
---| 'statusline'
---| 'tabline'
---| 'winbar'
---@class LualineHideOpts
---@field place LualineHideOptsPlace[]
---@field unhide boolean
---@param opts LualineHideOpts
local function hide(opts)
if opts == nil then
opts = {}
end
opts = vim.tbl_extend('keep', opts, {
place = { 'statusline', 'tabline', 'winbar' },
unhide = false,
})
local hide_fn = {
statusline = set_statusline,
tabline = set_tabline,
winbar = set_winbar,
}
for _, place in ipairs(opts.place) do
if hide_fn[place] then
hide_fn[place](not opts.unhide)
end
end
end
--- Check neovim compatibilitu
local function verify_nvim_version()
if vim.fn.has('nvim-0.7') == 1 then
return true
end
modules.utils_notices.add_notice([[
### Incompatible Neovim version
Lualine supports neovim 0.7 and up. It seems you're using a older version.
Please update to newer version. Or if you have atleast neovim 0.5 you
can use older compatible versions of lualine using compat tags like
`compat-nvim-0.5`, `compat-nvim-0.6`.
]])
return false
end
-- lualine.setup function
--- sets new user config
--- This function doesn't load components/theme etc... They are done before
--- first statusline redraw and after new config. This is more efficient when
--- lualine config is done in several setup calls as chunks. This way
--- we don't initialize components just to throw them away. Instead they are
--- initialized when we know we will use them.
--- sets &last_status to 2
---@param user_config table table
local function setup(user_config)
if package.loaded['lualine.utils.notices'] then
-- When notices module is not loaded there are no notices to clear.
modules.utils_notices.clear_notices()
end
if verify_nvim_version() then
config = modules.config_module.apply_configuration(user_config)
vim.cmd([[augroup lualine | exe "autocmd!" | augroup END]])
setup_theme()
-- load components & extensions
modules.loader.load_all(config)
set_statusline()
set_tabline()
set_winbar()
end
if package.loaded['lualine.utils.notices'] then
modules.utils_notices.notice_message_startup()
end
end
M = {
setup = setup,
statusline = status_dispatch('sections'),
tabline = tabline,
get_config = modules.config_module.get_config,
refresh = refresh,
winbar = status_dispatch('winbar'),
hide = hide,
}
return M

View File

@ -0,0 +1,291 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local lualine_require = require('lualine_require')
local require = lualine_require.require
local M = require('lualine.utils.class'):extend()
local modules = lualine_require.lazy_require {
highlight = 'lualine.highlight',
utils_notices = 'lualine.utils.notices',
fn_store = 'lualine.utils.fn_store',
}
-- Used to provide a unique id for each component
local component_no = 1
function M._reset_components()
component_no = 1
end
-- variable to store component output for manipulation
M.status = ''
function M:__tostring()
local str = 'Component: ' .. self.options.component_name
if self.debug then
str = str .. '\n---------------------\n' .. vim.inspect(self)
end
return str
end
M.__is_lualine_component = true
---initialize new component
---@param options table options for component
function M:init(options)
self.options = options or {}
component_no = component_no + 1
if not self.options.component_name then
self.options.component_name = tostring(component_no)
end
self.component_no = component_no
self:set_separator()
self:create_option_highlights()
self:set_on_click()
end
---sets the default separator for component based on whether the component
---is in left sections or right sections when separator option is omitted.
function M:set_separator()
if self.options.separator == nil then
if self.options.component_separators then
if self.options.self.section < 'x' then
self.options.separator = self.options.component_separators.left
else
self.options.separator = self.options.component_separators.right
end
end
end
end
---creates hl group from color option
function M:create_option_highlights()
-- set custom highlights
if self.options.color then
self.options.color_highlight = self:create_hl(self.options.color)
end
-- setup icon highlight
if type(self.options.icon) == 'table' and self.options.icon.color then
self.options.icon_color_highlight = self:create_hl(self.options.icon.color)
end
end
---Setup on click function so they can be added during drawing.
function M:set_on_click()
if self.options.on_click ~= nil then
if vim.fn.has('nvim-0.8') == 0 then
modules.utils_notices.add_notice(
'### Options.on_click\nSorry `on_click` can only be used in neovim 0.8 or higher.\n'
)
self.options.on_click = nil
return
end
self.on_click_id = modules.fn_store.register_fn(self.component_no, self.options.on_click)
end
end
---adds spaces to left and right of a component
function M:apply_padding()
local padding = self.options.padding
local l_padding, r_padding
if padding == nil then
padding = 1
end
if type(padding) == 'number' then
l_padding, r_padding = padding, padding
elseif type(padding) == 'table' then
l_padding, r_padding = padding.left, padding.right
end
if l_padding then
if self.status:find('%%#.*#') == 1 then
-- When component has changed the highlight at beginning
-- 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
function M:apply_highlights(default_highlight)
if self.options.color_highlight then
local hl_fmt
hl_fmt, M.color_fn_cache = self:format_hl(self.options.color_highlight)
self.status = hl_fmt .. self.status
end
if type(self.options.separator) ~= 'table' and self.status:find('%%#') then
-- Apply default highlight only when we aren't applying trans sep and
-- the component has changed it's hl. Since we won't be applying
-- regular sep in those cases so ending with default hl isn't necessary
self.status = self.status .. default_highlight
-- Also put it in applied sep so when sep get striped so does the hl
self.applied_separator = default_highlight
end
-- Prepend default hl when the component doesn't start with hl otherwise
-- color in previous component can cause side effect
if not self.status:find('^%%#') then
self.status = default_highlight .. self.status
end
end
---apply icon to component (appends/prepends component with icon)
function M:apply_icon()
local icon = self.options.icon
if self.options.icons_enabled and icon then
if type(icon) == 'table' then
icon = icon[1]
end
if
self.options.icon_color_highlight
and type(self.options.icon) == 'table'
and self.options.icon.align == 'right'
then
self.status = table.concat {
self.status,
' ',
self:format_hl(self.options.icon_color_highlight),
icon,
self:get_default_hl(),
}
elseif self.options.icon_color_highlight then
self.status = table.concat {
self:format_hl(self.options.icon_color_highlight),
icon,
self:get_default_hl(),
' ',
self.status,
}
elseif type(self.options.icon) == 'table' and self.options.icon.align == 'right' then
self.status = table.concat({ self.status, icon }, ' ')
else
self.status = table.concat({ icon, self.status }, ' ')
end
end
end
---apply separator at end of component only when
---custom highlights haven't affected background
function M:apply_separator()
local separator = self.options.separator
if type(separator) == 'table' then
if self.options.separator[2] == '' then
if self.options.self.section < 'x' then
separator = self.options.component_separators.left
else
separator = self.options.component_separators.right
end
else
return
end
end
if separator and #separator > 0 then
self.status = self.status .. separator
self.applied_separator = self.applied_separator .. separator
end
end
---apply transitional separator for the component
function M:apply_section_separators()
if type(self.options.separator) ~= 'table' then
return
end
if self.options.separator.left ~= nil and self.options.separator.left ~= '' then
self.status = string.format('%%z{%s}%s', self.options.separator.left, self.status)
self.strip_previous_separator = true
end
if self.options.separator.right ~= nil and self.options.separator.right ~= '' then
self.status = string.format('%s%%Z{%s}', self.status, self.options.separator.right)
end
end
---Add on click function description to already drawn item
function M:apply_on_click()
if self.on_click_id then
self.status = self:format_fn(self.on_click_id, self.status)
end
end
---remove separator from tail of this component.
---called by lualine.utils.sections.draw_section to manage unnecessary separators
function M:strip_separator()
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
function M:get_default_hl()
if self.options.color_highlight then
return self:format_hl(self.options.color_highlight)
elseif self.default_hl then
return self.default_hl
else
return modules.highlight.format_highlight(self.options.self.section)
end
end
---create a lualine highlight for color
---@param color table|string|function defined color for hl
---@param hint string|nil hint for hl name
---@return table an identifier to later retrieve the hl for application
function M:create_hl(color, hint)
hint = hint and self.options.component_name .. '_' .. hint or self.options.component_name
return modules.highlight.create_component_highlight_group(color, hint, self.options, false)
end
---Get stl formatted hl group for hl_token
---@param hl_token table identifier received from create_hl or create_component_highlight_group
---@return string stl formatted hl group for hl_token
function M:format_hl(hl_token)
return modules.highlight.component_format_highlight(hl_token)
end
---Wrap str with click format for function of id
---@param id number
---@param str string
---@return string
function M:format_fn(id, str)
return string.format("%%%d@v:lua.require'lualine.utils.fn_store'.call_fn@%s%%T", id, str)
end
-- luacheck: push no unused args
---actual function that updates a component. Must be overwritten with component functionality
function M:update_status(is_focused) end
-- luacheck: pop
---driver code of the class
---@param default_highlight string default hl group of section where component resides
---@param is_focused boolean|number whether drawing for active or inactive statusline.
---@return string stl formatted rendering string for component
function M:draw(default_highlight, is_focused)
self.status = ''
self.applied_separator = ''
if self.options.cond ~= nil and self.options.cond() ~= true then
return self.status
end
self.default_hl = default_highlight
local status = self:update_status(is_focused)
if self.options.fmt then
status = self.options.fmt(status or '', self)
end
if type(status) == 'string' and (#status > 0 or self.options.draw_empty) then
self.status = status
if #status > 0 then
self:apply_icon()
self:apply_padding()
end
self:apply_on_click()
self:apply_highlights(default_highlight)
self:apply_section_separators()
self:apply_separator()
end
return self.status
end
return M

View File

@ -0,0 +1,149 @@
local M = {}
local require = require('lualine_require').require
local utils = require('lualine.utils.utils')
-- vars
local current_git_branch = ''
local current_git_dir = ''
local branch_cache = {} -- stores last known branch for a buffer
local active_bufnr = '0'
-- os specific path separator
local sep = package.config:sub(1, 1)
-- event watcher to watch head file
-- Use file watch for non Windows and poll for Windows.
-- Windows doesn't like file watch for some reason.
local file_changed = sep ~= '\\' and vim.loop.new_fs_event() or vim.loop.new_fs_poll()
local git_dir_cache = {} -- Stores git paths that we already know of
---sets git_branch variable to branch name or commit hash if not on branch
---@param head_file string full path of .git/HEAD file
local function get_git_head(head_file)
local f_head = io.open(head_file)
if f_head then
local HEAD = f_head:read()
f_head:close()
local branch = HEAD:match('ref: refs/heads/(.+)$')
if branch then
current_git_branch = branch
else
current_git_branch = HEAD:sub(1, 6)
end
end
return nil
end
---updates the current value of git_branch and sets up file watch on HEAD file
local function update_branch()
active_bufnr = tostring(vim.api.nvim_get_current_buf())
file_changed:stop()
local git_dir = current_git_dir
if git_dir and #git_dir > 0 then
local head_file = git_dir .. sep .. 'HEAD'
get_git_head(head_file)
file_changed:start(
head_file,
sep ~= '\\' and {} or 1000,
vim.schedule_wrap(function()
-- reset file-watch
update_branch()
end)
)
else
-- set to '' when git dir was not found
current_git_branch = ''
end
branch_cache[vim.api.nvim_get_current_buf()] = current_git_branch
end
---updates the current value of current_git_branch and sets up file watch on HEAD file if value changed
local function update_current_git_dir(git_dir)
if current_git_dir ~= git_dir then
current_git_dir = git_dir
update_branch()
end
end
---returns full path to git directory for dir_path or current directory
---@param dir_path string|nil
---@return string|nil
function M.find_git_dir(dir_path)
local git_dir = vim.env.GIT_DIR
if git_dir then
update_current_git_dir(git_dir)
return git_dir
end
-- get file dir so we can search from that dir
local file_dir = dir_path or vim.fn.expand('%:p:h')
-- extract correct file dir from terminals
if file_dir and file_dir:match('term://.*') then
file_dir = vim.fn.expand(file_dir:gsub('term://(.+)//.+', '%1'))
end
local root_dir = file_dir
-- Search upward for .git file or folder
while root_dir do
if git_dir_cache[root_dir] then
git_dir = git_dir_cache[root_dir]
break
end
local git_path = root_dir .. sep .. '.git'
local git_file_stat = vim.loop.fs_stat(git_path)
if git_file_stat then
if git_file_stat.type == 'directory' then
git_dir = git_path
elseif git_file_stat.type == 'file' then
-- separate git-dir or submodule is used
local file = io.open(git_path)
if file then
git_dir = file:read()
git_dir = git_dir and git_dir:match('gitdir: (.+)$')
file:close()
end
-- submodule / relative file path
if git_dir and git_dir:sub(1, 1) ~= sep and not git_dir:match('^%a:.*$') then
git_dir = git_path:match('(.*).git') .. git_dir
end
end
if git_dir then
local head_file_stat = vim.loop.fs_stat(git_dir .. sep .. 'HEAD')
if head_file_stat and head_file_stat.type == 'file' then
break
else
git_dir = nil
end
end
end
root_dir = root_dir:match('(.*)' .. sep .. '.-')
end
git_dir_cache[file_dir] = git_dir
if dir_path == nil then
update_current_git_dir(git_dir)
end
return git_dir
end
---initializes git_branch module
function M.init()
-- run watch head on load so branch is present when component is loaded
M.find_git_dir()
-- update branch state of BufEnter as different Buffer may be on different repos
utils.define_autocmd('BufEnter', "lua require'lualine.components.branch.git_branch'.find_git_dir()")
end
function M.get_branch(bufnr)
if vim.g.actual_curbuf ~= nil and active_bufnr ~= vim.g.actual_curbuf then
-- Workaround for https://github.com/nvim-lualine/lualine.nvim/issues/286
-- See upstream issue https://github.com/neovim/neovim/issues/15300
-- Diff is out of sync re sync it.
M.find_git_dir()
end
if bufnr then
return branch_cache[bufnr] or ''
end
return current_git_branch
end
return M

View File

@ -0,0 +1,25 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local M = require('lualine.component'):extend()
local modules = require('lualine_require').lazy_require {
git_branch = 'lualine.components.branch.git_branch',
highlight = 'lualine.highlight',
utils = 'lualine.utils.utils',
}
-- Initializer
M.init = function(self, options)
M.super.init(self, options)
if not self.options.icon then
self.options.icon = '' -- e0a0
end
modules.git_branch.init()
end
M.update_status = function(_, is_focused)
local buf = (not is_focused and vim.api.nvim_get_current_buf())
local branch = modules.git_branch.get_branch(buf)
return modules.utils.stl_escape(branch)
end
return M

View File

@ -0,0 +1,192 @@
local Buffer = require('lualine.utils.class'):extend()
local modules = require('lualine_require').lazy_require {
highlight = 'lualine.highlight',
utils = 'lualine.utils.utils',
}
---initialize a new buffer from opts
---@param opts table
function Buffer:init(opts)
assert(opts.bufnr, 'Cannot create Buffer without bufnr')
self.bufnr = opts.bufnr
self.buf_index = opts.buf_index
self.options = opts.options
self.highlights = opts.highlights
self:get_props()
end
function Buffer:is_current()
return vim.api.nvim_get_current_buf() == self.bufnr
end
function Buffer:is_alternate()
return vim.fn.bufnr('#') == self.bufnr and not self:is_current()
end
---setup icons, modified status for buffer
function Buffer:get_props()
self.file = modules.utils.stl_escape(vim.api.nvim_buf_get_name(self.bufnr))
self.buftype = vim.api.nvim_buf_get_option(self.bufnr, 'buftype')
self.filetype = vim.api.nvim_buf_get_option(self.bufnr, 'filetype')
local modified = self.options.show_modified_status and vim.api.nvim_buf_get_option(self.bufnr, 'modified')
self.modified_icon = modified and self.options.symbols.modified or ''
self.alternate_file_icon = self:is_alternate() and self.options.symbols.alternate_file or ''
self.icon = ''
if self.options.icons_enabled then
local dev
local status, _ = pcall(require, 'nvim-web-devicons')
if not status then
dev, _ = '', ''
elseif self.filetype == 'TelescopePrompt' then
dev, _ = require('nvim-web-devicons').get_icon('telescope')
elseif self.filetype == 'fugitive' then
dev, _ = require('nvim-web-devicons').get_icon('git')
elseif self.filetype == 'vimwiki' then
dev, _ = require('nvim-web-devicons').get_icon('markdown')
elseif self.buftype == 'terminal' then
dev, _ = require('nvim-web-devicons').get_icon('zsh')
elseif vim.fn.isdirectory(self.file) == 1 then
dev, _ = self.options.symbols.directory, nil
else
dev, _ = require('nvim-web-devicons').get_icon(self.file, vim.fn.expand('#' .. self.bufnr .. ':e'))
end
if dev then
self.icon = dev .. ' '
end
end
end
---returns line configured for handling mouse click
---@param name string
---@return string
function Buffer:configure_mouse_click(name)
return string.format('%%%s@LualineSwitchBuffer@%s%%T', self.bufnr, name)
end
---returns rendered buffer
---@return string
function Buffer:render()
local name = self:name()
if self.options.fmt then
name = self.options.fmt(name or '', self)
end
if self.ellipse then -- show ellipsis
name = '...'
else
name = self:apply_mode(name)
end
name = Buffer.apply_padding(name, self.options.padding)
self.len = vim.fn.strchars(name)
-- setup for mouse clicks
local line = self:configure_mouse_click(name)
-- apply highlight
line = modules.highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')])
.. line
-- apply separators
if self.options.self.section < 'x' and not self.first then
local sep_before = self:separator_before()
line = sep_before .. line
self.len = self.len + vim.fn.strchars(sep_before)
elseif self.options.self.section >= 'x' and not self.last then
local sep_after = self:separator_after()
line = line .. sep_after
self.len = self.len + vim.fn.strchars(sep_after)
end
return line
end
---apply separator before current buffer
---@return string
function Buffer:separator_before()
if self.current or self.aftercurrent then
return '%Z{' .. self.options.section_separators.left .. '}'
else
return self.options.component_separators.left
end
end
---apply separator after current buffer
---@return string
function Buffer:separator_after()
if self.current or self.beforecurrent then
return '%z{' .. self.options.section_separators.right .. '}'
else
return self.options.component_separators.right
end
end
---returns name of current buffer after filtering special buffers
---@return string
function Buffer:name()
if self.options.filetype_names[self.filetype] then
return self.options.filetype_names[self.filetype]
elseif self.buftype == 'help' then
return 'help:' .. vim.fn.fnamemodify(self.file, ':t:r')
elseif self.buftype == 'terminal' then
local match = string.match(vim.split(self.file, ' ')[1], 'term:.*:(%a+)')
return match ~= nil and match or vim.fn.fnamemodify(vim.env.SHELL, ':t')
elseif self.buftype == 'quickfix' then
local is_loclist = 0 ~= vim.fn.getloclist(0, { filewinid = 1 }).filewinid
return is_loclist and 'Location list' or 'Quickfix List'
elseif vim.fn.isdirectory(self.file) == 1 then
return vim.fn.fnamemodify(self.file, ':p:.')
elseif self.file == '' then
return '[No Name]'
end
local name
if self.options.show_filename_only then
name = vim.fn.fnamemodify(self.file, ':t')
else
name = vim.fn.pathshorten(vim.fn.fnamemodify(self.file, ':p:.'))
end
if self.options.hide_filename_extension then
name = vim.fn.fnamemodify(name, ':r')
end
return name
end
---adds spaces to left and right
function Buffer.apply_padding(str, padding)
local l_padding, r_padding = 1, 1
if type(padding) == 'number' then
l_padding, r_padding = padding, padding
elseif type(padding) == 'table' then
l_padding, r_padding = padding.left or 0, padding.right or 0
end
return string.rep(' ', l_padding) .. str .. string.rep(' ', r_padding)
end
function Buffer:apply_mode(name)
if self.options.mode == 0 then
return string.format('%s%s%s%s', self.alternate_file_icon, self.icon, name, self.modified_icon)
end
if self.options.mode == 1 then
return string.format('%s%s %s%s', self.alternate_file_icon, self.buf_index or '', self.icon, self.modified_icon)
end
if self.options.mode == 2 then
return string.format(
'%s%s %s%s%s',
self.alternate_file_icon,
self.buf_index or '',
self.icon,
name,
self.modified_icon
)
end
if self.options.mode == 3 then
return string.format('%s%s %s%s', self.alternate_file_icon, self.bufnr or '', self.icon, self.modified_icon)
end
-- if self.options.mode == 4 then
return string.format('%s%s %s%s%s', self.alternate_file_icon, self.bufnr or '', self.icon, name, self.modified_icon)
end
return Buffer

View File

@ -0,0 +1,245 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local require = require('lualine_require').require
local Buffer = require('lualine.components.buffers.buffer')
local M = require('lualine.component'):extend()
local highlight = require('lualine.highlight')
local default_options = {
show_filename_only = true,
hide_filename_extension = false,
show_modified_status = true,
mode = 0,
max_length = 0,
filetype_names = {
TelescopePrompt = 'Telescope',
dashboard = 'Dashboard',
packer = 'Packer',
fzf = 'FZF',
alpha = 'Alpha',
},
use_mode_colors = false,
buffers_color = {
active = nil,
inactive = nil,
},
symbols = {
modified = '',
alternate_file = '#',
directory = '',
},
}
-- This function is duplicated in tabs
---returns the proper hl for buffer in section. Used for setting default highlights
---@param section string name of section buffers component is in
---@param is_active boolean
---@return string hl name
local function get_hl(section, is_active)
local suffix = is_active and highlight.get_mode_suffix() or '_inactive'
local section_redirects = {
lualine_x = 'lualine_c',
lualine_y = 'lualine_b',
lualine_z = 'lualine_a',
}
if section_redirects[section] then
section = highlight.highlight_exists(section .. suffix) and section or section_redirects[section]
end
return section .. suffix
end
function M:init(options)
M.super.init(self, options)
-- if use_mode_colors is set, use a function so that the colors update
local default_active = options.use_mode_colors
and function()
return get_hl('lualine_' .. options.self.section, true)
end
or get_hl('lualine_' .. options.self.section, true)
default_options.buffers_color = {
active = default_active,
inactive = get_hl('lualine_' .. options.self.section, false),
}
self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
if self.options.component_name == 'buffers' then
self.highlights = {
active = self:create_hl(self.options.buffers_color.active, 'active'),
inactive = self:create_hl(self.options.buffers_color.inactive, 'inactive'),
}
end
end
function M:new_buffer(bufnr, buf_index)
bufnr = bufnr or vim.api.nvim_get_current_buf()
buf_index = buf_index or ''
return Buffer:new {
bufnr = bufnr,
buf_index = buf_index,
options = self.options,
highlights = self.highlights,
}
end
function M:buffers()
local buffers = {}
M.bufpos2nr = {}
for b = 1, vim.fn.bufnr('$') do
if vim.fn.buflisted(b) ~= 0 and vim.api.nvim_buf_get_option(b, 'buftype') ~= 'quickfix' then
buffers[#buffers + 1] = self:new_buffer(b, #buffers + 1)
M.bufpos2nr[#buffers] = b
end
end
return buffers
end
function M:update_status()
local data = {}
local buffers = self:buffers()
local current = -2
-- mark the first, last, current, before current, after current buffers
-- for rendering
if buffers[1] then
buffers[1].first = true
end
if buffers[#buffers] then
buffers[#buffers].last = true
end
for i, buffer in ipairs(buffers) do
if buffer:is_current() then
buffer.current = true
current = i
end
end
if buffers[current - 1] then
buffers[current - 1].beforecurrent = true
end
if buffers[current + 1] then
buffers[current + 1].aftercurrent = true
end
local max_length = self.options.max_length
if type(max_length) == 'function' then
max_length = max_length(self)
end
if max_length == 0 then
max_length = math.floor(2 * vim.o.columns / 3)
end
local total_length
for i, buffer in pairs(buffers) do
if buffer.current then
current = i
end
end
-- start drawing from current buffer and draw left and right of it until
-- all buffers are drawn or max_length has been reached.
if current == -2 then
local b = self:new_buffer()
b.current = true
if self.options.self.section < 'x' then
b.last = true
if #buffers > 0 then
buffers[#buffers].last = nil
end
buffers[#buffers + 1] = b
current = #buffers
else
b.first = true
if #buffers > 0 then
buffers[1].first = nil
end
table.insert(buffers, 1, b)
current = 1
end
end
local current_buffer = buffers[current]
data[#data + 1] = current_buffer:render()
total_length = current_buffer.len
local i = 0
local before, after
while true do
i = i + 1
before = buffers[current - i]
after = buffers[current + i]
local rendered_before, rendered_after
if before == nil and after == nil then
break
end
-- draw left most undrawn buffer if fits in max_length
if before then
rendered_before = before:render()
total_length = total_length + before.len
if total_length > max_length then
break
end
table.insert(data, 1, rendered_before)
end
-- draw right most undrawn buffer if fits in max_length
if after then
rendered_after = after:render()
total_length = total_length + after.len
if total_length > max_length then
break
end
data[#data + 1] = rendered_after
end
end
-- draw ellipsis (...) on relevant sides if all buffers don't fit in max_length
if total_length > max_length then
if before ~= nil then
before.ellipse = true
before.first = true
table.insert(data, 1, before:render())
end
if after ~= nil then
after.ellipse = true
after.last = true
data[#data + 1] = after:render()
end
end
return table.concat(data)
end
function M:draw()
self.status = ''
self.applied_separator = ''
if self.options.cond ~= nil and self.options.cond() ~= true then
return self.status
end
local status = self:update_status()
if type(status) == 'string' and #status > 0 then
self.status = status
self:apply_section_separators()
self:apply_separator()
end
return self.status
end
function M.buffer_jump(buf_pos, bang)
if buf_pos == '$' then
buf_pos = #M.bufpos2nr
else
buf_pos = tonumber(buf_pos)
end
if buf_pos < 1 or buf_pos > #M.bufpos2nr then
if bang ~= '!' then
error('Error: Unable to jump buffer position out of range')
else
return
end
end
vim.api.nvim_set_current_buf(M.bufpos2nr[buf_pos])
end
vim.cmd([[
function! LualineSwitchBuffer(bufnr, mouseclicks, mousebutton, modifiers)
execute ":buffer " . a:bufnr
endfunction
command! -nargs=1 -bang LualineBuffersJump call v:lua.require'lualine.components.buffers'.buffer_jump(<f-args>, "<bang>")
]])
return M

View File

@ -0,0 +1,31 @@
-- Copyright (c) 2023 Willothy
-- MIT license, see LICENSE for more details.
local lualine_require = require('lualine_require')
local M = lualine_require.require('lualine.component'):extend()
local default_options = {
-- default, us, uk, iso, or format (ex. "%d/%m/%Y ...")
style = 'default',
}
function M:init(options)
M.super.init(self, options)
self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
end
function M:update_status()
local fmt = self.options.style
if self.options.style == 'default' then
fmt = '%A, %B %d | %H:%M'
elseif self.options.style == 'us' then
fmt = '%m/%d/%Y'
elseif self.options.style == 'uk' then
fmt = '%d/%m/%Y'
elseif self.options.style == 'iso' then
fmt = '%Y-%m-%d'
end
return os.date(fmt)
end
return M

View File

@ -0,0 +1,59 @@
local require = require('lualine_require').require
local utils = require('lualine.utils.utils')
local M = {}
-- default symbols for diagnostics component
M.symbols = {
icons = {
error = '󰅚 ', -- x000f015a
warn = '󰀪 ', -- x000f002a
info = '󰋽 ', -- x000f02fd
hint = '󰌶 ', -- x000f0336
},
no_icons = { error = 'E:', warn = 'W:', info = 'I:', hint = 'H:' },
}
-- default options for diagnostics component
M.options = {
colored = true,
update_in_insert = false,
always_visible = false,
sources = { 'nvim_diagnostic', 'coc' },
sections = { 'error', 'warn', 'info', 'hint' },
}
function M.apply_default_colors(opts)
local default_diagnostics_color = {
error = {
fg = utils.extract_color_from_hllist(
{ 'fg', 'sp' },
{ 'DiagnosticError', 'LspDiagnosticsDefaultError', 'DiffDelete' },
'#e32636'
),
},
warn = {
fg = utils.extract_color_from_hllist(
{ 'fg', 'sp' },
{ 'DiagnosticWarn', 'LspDiagnosticsDefaultWarning', 'DiffText' },
'#ffa500'
),
},
info = {
fg = utils.extract_color_from_hllist(
{ 'fg', 'sp' },
{ 'DiagnosticInfo', 'LspDiagnosticsDefaultInformation', 'Normal' },
'#ffffff'
),
},
hint = {
fg = utils.extract_color_from_hllist(
{ 'fg', 'sp' },
{ 'DiagnosticHint', 'LspDiagnosticsDefaultHint', 'DiffChange' },
'#273faf'
),
},
}
opts.diagnostics_color = vim.tbl_deep_extend('keep', opts.diagnostics_color or {}, default_diagnostics_color)
end
return M

View File

@ -0,0 +1,111 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local lualine_require = require('lualine_require')
local modules = lualine_require.lazy_require {
default_config = 'lualine.components.diagnostics.config',
sources = 'lualine.components.diagnostics.sources',
highlight = 'lualine.highlight',
utils = 'lualine.utils.utils',
utils_notices = 'lualine.utils.notices',
}
local M = lualine_require.require('lualine.component'):extend()
M.diagnostics_sources = modules.sources.sources
M.get_diagnostics = modules.sources.get_diagnostics
-- Initializer
function M:init(options)
-- Run super()
M.super.init(self, options)
-- Apply default options
modules.default_config.apply_default_colors(self.options)
self.options = vim.tbl_deep_extend('keep', self.options or {}, modules.default_config.options)
-- Apply default symbols
self.symbols = vim.tbl_extend(
'keep',
self.options.symbols or {},
self.options.icons_enabled ~= false and modules.default_config.symbols.icons
or modules.default_config.symbols.no_icons
)
-- Initialize highlight groups
if self.options.colored then
self.highlight_groups = {
error = self:create_hl(self.options.diagnostics_color.error, 'error'),
warn = self:create_hl(self.options.diagnostics_color.warn, 'warn'),
info = self:create_hl(self.options.diagnostics_color.info, 'info'),
hint = self:create_hl(self.options.diagnostics_color.hint, 'hint'),
}
end
-- Initialize variable to store last update so we can use it in insert
-- mode for no update_in_insert
self.last_diagnostics_count = {}
-- Error out no source
if #self.options.sources < 1 then
modules.utils_notices.add_notice(
'### diagnostics.sources\n\nno sources for diagnostics configured.\nPlease specify which diagnostics source you want lualine to use with `sources` option.\n'
)
end
end
function M:update_status()
local bufnr = vim.api.nvim_get_current_buf()
local diagnostics_count
local result = {}
if self.options.update_in_insert or vim.api.nvim_get_mode().mode:sub(1, 1) ~= 'i' then
local error_count, warning_count, info_count, hint_count = 0, 0, 0, 0
local diagnostic_data = modules.sources.get_diagnostics(self.options.sources)
-- sum all the counts
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
hint_count = hint_count + data.hint
end
diagnostics_count = {
error = error_count,
warn = warning_count,
info = info_count,
hint = hint_count,
}
-- Save count for insert mode
self.last_diagnostics_count[bufnr] = diagnostics_count
else -- Use cached count in insert mode with update_in_insert disabled
diagnostics_count = self.last_diagnostics_count[bufnr] or { error = 0, warn = 0, info = 0, hint = 0 }
end
local always_visible = false
if type(self.options.always_visible) == 'boolean' then
always_visible = self.options.always_visible
elseif type(self.options.always_visible) == 'function' then
always_visible = self.options.always_visible()
end
-- format the counts with symbols and highlights
if self.options.colored then
local colors, bgs = {}, {}
for name, hl in pairs(self.highlight_groups) do
colors[name] = self:format_hl(hl)
bgs[name] = modules.utils.extract_highlight_colors(colors[name]:match('%%#(.-)#'), 'bg')
end
local previous_section, padding
for _, section in ipairs(self.options.sections) do
if diagnostics_count[section] ~= nil and (always_visible or diagnostics_count[section] > 0) then
padding = previous_section and (bgs[previous_section] ~= bgs[section]) and ' ' or ''
previous_section = section
table.insert(result, colors[section] .. padding .. self.symbols[section] .. diagnostics_count[section])
end
end
else
for _, section in ipairs(self.options.sections) do
if diagnostics_count[section] ~= nil and (always_visible or diagnostics_count[section] > 0) then
table.insert(result, self.symbols[section] .. diagnostics_count[section])
end
end
end
return table.concat(result, ' ')
end
return M

View File

@ -0,0 +1,100 @@
local M = {}
---functions that how how to retrieve diagnostics from specific source.
---returns error_count:number, warning_count:number,
--- info_count:number, hint_count:number
M.sources = {
nvim_lsp = function()
local error_count, warning_count, info_count, hint_count
local diagnostics = vim.diagnostic.get(0)
local count = { 0, 0, 0, 0 }
for _, diagnostic in ipairs(diagnostics) do
if vim.startswith(vim.diagnostic.get_namespace(diagnostic.namespace).name, 'vim.lsp') then
count[diagnostic.severity] = count[diagnostic.severity] + 1
end
end
error_count = count[vim.diagnostic.severity.ERROR]
warning_count = count[vim.diagnostic.severity.WARN]
info_count = count[vim.diagnostic.severity.INFO]
hint_count = count[vim.diagnostic.severity.HINT]
return error_count, warning_count, info_count, hint_count
end,
nvim_workspace_diagnostic = function()
local diag_severity = vim.diagnostic.severity
local function workspace_diag(severity)
local count = vim.diagnostic.get(nil, { severity = severity })
return vim.tbl_count(count)
end
return workspace_diag(diag_severity.ERROR),
workspace_diag(diag_severity.WARN),
workspace_diag(diag_severity.INFO),
workspace_diag(diag_severity.HINT)
end,
nvim_diagnostic = function()
local diagnostics = vim.diagnostic.get(0)
local count = { 0, 0, 0, 0 }
for _, diagnostic in ipairs(diagnostics) do
count[diagnostic.severity] = count[diagnostic.severity] + 1
end
return count[vim.diagnostic.severity.ERROR],
count[vim.diagnostic.severity.WARN],
count[vim.diagnostic.severity.INFO],
count[vim.diagnostic.severity.HINT]
end,
coc = function()
local data = vim.b.coc_diagnostic_info
if data then
return data.error, data.warning, data.information, data.hint
else
return 0, 0, 0, 0
end
end,
ale = function()
local ok, data = pcall(vim.fn['ale#statusline#Count'], vim.api.nvim_get_current_buf())
if ok then
return data.error + data.style_error, data.warning + data.style_warning, data.info, 0
else
return 0, 0, 0, 0
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, data.hint
else
return 0, 0, 0, 0
end
end,
}
---returns list of diagnostics count from all sources
---@param sources table list of sources
---@return table {{error_count, warning_count, info_count, hint_count}}
M.get_diagnostics = function(sources)
local result = {}
for index, source in ipairs(sources) do
if type(source) == 'string' then
local error_count, warning_count, info_count, hint_count = M.sources[source]()
result[index] = {
error = error_count,
warn = warning_count,
info = info_count,
hint = hint_count,
}
elseif type(source) == 'function' then
local source_result = source()
source_result = type(source_result) == 'table' and source_result or {}
result[index] = {
error = source_result.error or 0,
warn = source_result.warn or 0,
info = source_result.info or 0,
hint = source_result.hint or 0,
}
end
end
return result
end
return M

View File

@ -0,0 +1,138 @@
local lualine_require = require('lualine_require')
local modules = lualine_require.lazy_require {
utils = 'lualine.utils.utils',
Job = 'lualine.utils.job',
}
local M = {}
-- Vars
-- variable to store git diff stats
local git_diff = nil
-- accumulates output from diff process
local diff_output_cache = {}
-- variable to store git_diff job
local diff_job = nil
local active_bufnr = '0'
local diff_cache = {} -- Stores last known value of diff of a buffer
---initialize the module
---param opts table
function M.init(opts)
if type(opts.source) == 'function' then
M.src = opts.source
else
modules.utils.define_autocmd('BufEnter', "lua require'lualine.components.diff.git_diff'.update_diff_args()")
modules.utils.define_autocmd('BufWritePost', "lua require'lualine.components.diff.git_diff'.update_git_diff()")
M.update_diff_args()
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 }
---@param bufnr number|nil
function M.get_sign_count(bufnr)
if bufnr then
return diff_cache[bufnr]
end
if M.src then
git_diff = M.src()
diff_cache[vim.api.nvim_get_current_buf()] = git_diff
elseif vim.g.actual_curbuf ~= nil and active_bufnr ~= vim.g.actual_curbuf then
-- Workaround for https://github.com/nvim-lualine/lualine.nvim/issues/286
-- See upstream issue https://github.com/neovim/neovim/issues/15300
-- Diff is out of sync re sync it.
M.update_diff_args()
end
return git_diff
end
---process diff data and update git_diff{ added, removed, modified }
---@param data string output on stdout od git diff job
local function process_diff(data)
-- Adapted from https://github.com/wbthomason/nvim-vcs.lua
local added, removed, modified = 0, 0, 0
for _, line in ipairs(data) do
if string.find(line, [[^@@ ]]) then
local tokens = vim.fn.matchlist(line, [[^@@ -\v(\d+),?(\d*) \+(\d+),?(\d*)]])
local line_stats = {
mod_count = tokens[3] == nil and 0 or tokens[3] == '' and 1 or tonumber(tokens[3]),
new_count = tokens[5] == nil and 0 or tokens[5] == '' and 1 or tonumber(tokens[5]),
}
if line_stats.mod_count == 0 and line_stats.new_count > 0 then
added = added + line_stats.new_count
elseif line_stats.mod_count > 0 and line_stats.new_count == 0 then
removed = removed + line_stats.mod_count
else
local min = math.min(line_stats.mod_count, line_stats.new_count)
modified = modified + min
added = added + line_stats.new_count - min
removed = removed + line_stats.mod_count - min
end
end
end
git_diff = { added = added, modified = modified, removed = removed }
end
---updates the job args
function M.update_diff_args()
-- Don't show git diff when current buffer doesn't have a filename
active_bufnr = tostring(vim.api.nvim_get_current_buf())
if #vim.fn.expand('%') == 0 then
M.diff_args = nil
git_diff = nil
return
end
M.diff_args = {
cmd = string.format(
[[git -C %s --no-pager diff --no-color --no-ext-diff -U0 -- %s]],
vim.fn.expand('%:h'),
vim.fn.expand('%:t')
),
on_stdout = function(_, data)
if next(data) then
diff_output_cache = vim.list_extend(diff_output_cache, data)
end
end,
on_stderr = function(_, data)
data = table.concat(data, '\n')
if #data > 0 then
git_diff = nil
diff_output_cache = {}
end
end,
on_exit = function()
if #diff_output_cache > 0 then
process_diff(diff_output_cache)
else
git_diff = { added = 0, modified = 0, removed = 0 }
end
diff_cache[vim.api.nvim_get_current_buf()] = git_diff
end,
}
M.update_git_diff()
end
---update git_diff variable
function M.update_git_diff()
if M.diff_args then
diff_output_cache = {}
if diff_job then
diff_job:stop()
end
diff_job = modules.Job(M.diff_args)
if diff_job then
diff_job:start()
end
end
end
return M

View File

@ -0,0 +1,93 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local lualine_require = require('lualine_require')
local modules = lualine_require.lazy_require {
git_diff = 'lualine.components.diff.git_diff',
utils = 'lualine.utils.utils',
utils_notices = 'lualine.utils.notices',
highlight = 'lualine.highlight',
}
local M = lualine_require.require('lualine.component'):extend()
local default_options = {
colored = true,
symbols = { added = '+', modified = '~', removed = '-' },
}
local function apply_default_colors(opts)
local default_diff_color = {
added = {
fg = modules.utils.extract_color_from_hllist(
'fg',
{ 'LuaLineDiffAdd', 'GitSignsAdd', 'GitGutterAdd', 'DiffAdded', 'DiffAdd' },
'#90ee90'
),
},
modified = {
fg = modules.utils.extract_color_from_hllist(
'fg',
{ 'LuaLineDiffChange', 'GitSignsChange', 'GitGutterChange', 'DiffChanged', 'DiffChange' },
'#f0e130'
),
},
removed = {
fg = modules.utils.extract_color_from_hllist(
'fg',
{ 'LuaLineDiffDelete', 'GitSignsDelete', 'GitGutterDelete', 'DiffRemoved', 'DiffDelete' },
'#ff0038'
),
},
}
opts.diff_color = vim.tbl_deep_extend('keep', opts.diff_color or {}, default_diff_color)
end
-- Initializer
function M:init(options)
M.super.init(self, options)
apply_default_colors(self.options)
self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
-- create highlights and save highlight_name in highlights table
if self.options.colored then
self.highlights = {
added = self:create_hl(self.options.diff_color.added, 'added'),
modified = self:create_hl(self.options.diff_color.modified, 'modified'),
removed = self:create_hl(self.options.diff_color.removed, 'removed'),
}
end
modules.git_diff.init(self.options)
end
-- Function that runs every time statusline is updated
function M:update_status(is_focused)
local git_diff = modules.git_diff.get_sign_count((not is_focused and vim.api.nvim_get_current_buf()))
if 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] = self:format_hl(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 self.options.colored then
table.insert(result, colors[name] .. self.options.symbols[name] .. git_diff[name])
else
table.insert(result, self.options.symbols[name] .. git_diff[name])
end
end
end
if #result > 0 then
return table.concat(result, ' ')
else
return ''
end
end
return M

View File

@ -0,0 +1,7 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local function encoding()
return vim.opt.fileencoding:get()
end
return encoding

View File

@ -0,0 +1,30 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local M = require('lualine.component'):extend()
-- stylua: ignore
local symbols = {
unix = '', -- e712
dos = '', -- e70f
mac = '', -- e711
}
-- Initializer
function M:init(options)
-- Run super()
M.super.init(self, options)
-- Apply default symbols
self.symbols = vim.tbl_extend('keep', self.options.symbols or {}, symbols)
end
-- Function that runs every time statusline is updated
function M:update_status()
local format = vim.bo.fileformat
if self.options.icons_enabled then
return self.symbols[format] or format
else
return format
end
end
return M

View File

@ -0,0 +1,119 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local M = require('lualine.component'):extend()
local modules = require('lualine_require').lazy_require {
utils = 'lualine.utils.utils',
}
local default_options = {
symbols = {
modified = '[+]',
readonly = '[-]',
unnamed = '[No Name]',
newfile = '[New]',
},
file_status = true,
newfile_status = false,
path = 0,
shorting_target = 40,
}
local function is_new_file()
local filename = vim.fn.expand('%')
return filename ~= '' and vim.bo.buftype == '' and vim.fn.filereadable(filename) == 0
end
---shortens path by turning apple/orange -> a/orange
---@param path string
---@param sep string path separator
---@param max_len integer maximum length of the full filename string
---@return string
local function shorten_path(path, sep, max_len)
local len = #path
if len <= max_len then
return path
end
local segments = vim.split(path, sep)
for idx = 1, #segments - 1 do
if len <= max_len then
break
end
local segment = segments[idx]
local shortened = segment:sub(1, vim.startswith(segment, '.') and 2 or 1)
segments[idx] = shortened
len = len - (#segment - #shortened)
end
return table.concat(segments, sep)
end
local function filename_and_parent(path, sep)
local segments = vim.split(path, sep)
if #segments == 0 then
return path
elseif #segments == 1 then
return segments[#segments]
else
return table.concat({ segments[#segments - 1], segments[#segments] }, sep)
end
end
M.init = function(self, options)
M.super.init(self, options)
self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
end
M.update_status = function(self)
local path_separator = package.config:sub(1, 1)
local data
if self.options.path == 1 then
-- relative path
data = vim.fn.expand('%:~:.')
elseif self.options.path == 2 then
-- absolute path
data = vim.fn.expand('%:p')
elseif self.options.path == 3 then
-- absolute path, with tilde
data = vim.fn.expand('%:p:~')
elseif self.options.path == 4 then
-- filename and immediate parent
data = filename_and_parent(vim.fn.expand('%:p:~'), path_separator)
else
-- just filename
data = vim.fn.expand('%:t')
end
if data == '' then
data = self.options.symbols.unnamed
end
if self.options.shorting_target ~= 0 then
local windwidth = self.options.globalstatus and vim.go.columns or vim.fn.winwidth(0)
local estimated_space_available = windwidth - self.options.shorting_target
data = shorten_path(data, path_separator, estimated_space_available)
end
data = modules.utils.stl_escape(data)
local symbols = {}
if self.options.file_status then
if vim.bo.modified then
table.insert(symbols, self.options.symbols.modified)
end
if vim.bo.modifiable == false or vim.bo.readonly == true then
table.insert(symbols, self.options.symbols.readonly)
end
end
if self.options.newfile_status and is_new_file() then
table.insert(symbols, self.options.symbols.newfile)
end
return data .. (#symbols > 0 and ' ' .. table.concat(symbols, '') or '')
end
return M

View File

@ -0,0 +1,25 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local function filesize()
local file = vim.fn.expand('%:p')
if file == nil or #file == 0 then
return ''
end
local size = vim.fn.getfsize(file)
if size <= 0 then
return ''
end
local suffixes = { 'b', 'k', 'm', 'g' }
local i = 1
while size > 1024 and i < #suffixes do
size = size / 1024
i = i + 1
end
local format = i == 1 and '%d%s' or '%.1f%s'
return string.format(format, size, suffixes[i])
end
return filesize

View File

@ -0,0 +1,82 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local lualine_require = require('lualine_require')
local modules = lualine_require.lazy_require {
highlight = 'lualine.highlight',
utils = 'lualine.utils.utils',
}
local M = lualine_require.require('lualine.component'):extend()
local default_options = {
colored = true,
icon_only = false,
}
function M:init(options)
M.super.init(self, options)
self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
self.icon_hl_cache = {}
end
function M.update_status()
local ft = vim.bo.filetype or ''
return modules.utils.stl_escape(ft)
end
function M:apply_icon()
if not self.options.icons_enabled then
return
end
local icon, icon_highlight_group
local ok, devicons = pcall(require, 'nvim-web-devicons')
if ok then
icon, icon_highlight_group = devicons.get_icon(vim.fn.expand('%:t'))
if icon == nil then
icon, icon_highlight_group = devicons.get_icon_by_filetype(vim.bo.filetype)
end
if icon == nil and icon_highlight_group == nil then
icon = ''
icon_highlight_group = 'DevIconDefault'
end
if icon then
icon = icon .. ' '
end
if self.options.colored then
local highlight_color = modules.utils.extract_highlight_colors(icon_highlight_group, 'fg')
if highlight_color then
local default_highlight = self:get_default_hl()
local icon_highlight = self.icon_hl_cache[highlight_color]
if not icon_highlight or not modules.highlight.highlight_exists(icon_highlight.name .. '_normal') then
icon_highlight = self:create_hl({ fg = highlight_color }, icon_highlight_group)
self.icon_hl_cache[highlight_color] = icon_highlight
end
icon = self:format_hl(icon_highlight) .. icon .. default_highlight
end
end
else
ok = vim.fn.exists('*WebDevIconsGetFileTypeSymbol')
if ok ~= 0 then
icon = vim.fn.WebDevIconsGetFileTypeSymbol()
if icon then
icon = icon .. ' '
end
end
end
if not icon then
return
end
if self.options.icon_only then
self.status = icon
elseif type(self.options.icon) == 'table' and self.options.icon.align == 'right' then
self.status = self.status .. ' ' .. icon
else
self.status = icon .. self.status
end
end
return M

View File

@ -0,0 +1,11 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local modules = require('lualine_require').lazy_require {
utils = 'lualine.utils.utils',
}
local function hostname()
return modules.utils.stl_escape(vim.loop.os_gethostname())
end
return hostname

View File

@ -0,0 +1,9 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local function location()
local line = vim.fn.line('.')
local col = vim.fn.virtcol('.')
return string.format('%3d:%-2d', line, col)
end
return location

View File

@ -0,0 +1,4 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local get_mode = require('lualine.utils.mode').get_mode
return get_mode

View File

@ -0,0 +1,15 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local function progress()
local cur = vim.fn.line('.')
local total = vim.fn.line('$')
if cur == 1 then
return 'Top'
elseif cur == total then
return 'Bot'
else
return string.format('%2d%%%%', math.floor(cur / total * 100))
end
end
return progress

View File

@ -0,0 +1,31 @@
local M = require('lualine.component'):extend()
local default_options = {
maxcount = 999,
timeout = 500,
}
-- Initializer
function M:init(options)
-- Run super()
M.super.init(self, options)
-- Apply default options
self.options = vim.tbl_extend('keep', self.options or {}, default_options)
end
-- Function that runs every time statusline is updated
function M:update_status()
if vim.v.hlsearch == 0 then
return ''
end
local ok, result = pcall(vim.fn.searchcount, { maxcount = self.options.maxcount, timeout = self.options.timeout })
if not ok or next(result) == nil then
return ''
end
local denominator = math.min(result.total, result.maxcount)
return string.format('[%d/%d]', result.current, denominator)
end
return M

View File

@ -0,0 +1,16 @@
local function selectioncount()
local mode = vim.fn.mode(true)
local line_start, col_start = vim.fn.line('v'), vim.fn.col('v')
local line_end, col_end = vim.fn.line('.'), vim.fn.col('.')
if mode:match('') then
return string.format('%dx%d', math.abs(line_start - line_end) + 1, math.abs(col_start - col_end) + 1)
elseif mode:match('V') or line_start ~= line_end then
return math.abs(line_start - line_end) + 1
elseif mode:match('v') then
return math.abs(col_start - col_end) + 1
else
return ''
end
end
return selectioncount

View File

@ -0,0 +1,48 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local M = require('lualine.component'):extend()
function M:update_status()
local component = self.options[1]
local ok, status
if self.options.type == nil then
ok, status = pcall(M.lua_eval, component)
if not ok then
status = M.vim_function(component)
end
else
if self.options.type == 'lua_expr' then
ok, status = pcall(M.lua_eval, component)
if not ok then
status = nil
end
elseif self.options.type == 'vim_fun' then
status = M.vim_function(component)
end
end
return status
end
---evaluate the lua code and return it's result as string
---@param code string
---@return string
function M.lua_eval(code)
local result = loadstring('return ' .. code)()
assert(result, 'String expected got nil')
return tostring(result)
end
---call vim function (name) and return it's result as string
---@param name string
---@return string
function M.vim_function(name)
-- vim function component
local ok, return_val = pcall(vim.api.nvim_call_function, name, {})
if not ok then
return ''
end -- function call failed
ok, return_val = pcall(tostring, return_val)
return ok and return_val or ''
end
return M

View File

@ -0,0 +1,21 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local M = require('lualine.component'):extend()
M.update_status = function(self, is_focused)
-- 1st element in options table is the function provided by config
local ok, retval
ok, retval = pcall(self.options[1], self, is_focused)
if not ok then
return ''
end
if type(retval) ~= 'string' then
ok, retval = pcall(tostring, retval)
if not ok then
return ''
end
end
return retval
end
return M

View File

@ -0,0 +1,37 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local require = require('lualine_require').require
local M = require('lualine.component'):extend()
local utils = require('lualine.utils.utils')
function M:update_status()
local component = self.options[1]
-- vim variable 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 variable aren't present
if not (scope and var_name) then
return ''
end
-- Support accessing keys within dictionary
-- https://github.com/nvim-lualine/lualine.nvim/issues/25#issuecomment-907374548
local name_chunks = vim.split(var_name, '%.')
local return_val = vim[scope][name_chunks[1]]
for i = 2, #name_chunks do
if return_val == nil then
break
end
return_val = return_val[name_chunks[i]]
end
if return_val == nil then
return ''
end
local ok
ok, return_val = pcall(tostring, return_val)
return ok and utils.stl_escape(return_val) or ''
end
return M

View File

@ -0,0 +1,193 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local require = require('lualine_require').require
local Tab = require('lualine.components.tabs.tab')
local M = require('lualine.component'):extend()
local highlight = require('lualine.highlight')
local default_options = {
max_length = 0,
tab_max_length = 40,
mode = 0,
use_mode_colors = false,
path = 0,
tabs_color = {
active = nil,
inactive = nil,
},
show_modified_status = true,
symbols = {
modified = '[+]',
},
}
-- This function is duplicated in buffers
---returns the proper hl for tab in section. Used for setting default highlights
---@param section string name of section tabs component is in
---@param is_active boolean
---@return string hl name
local function get_hl(section, is_active)
local suffix = is_active and highlight.get_mode_suffix() or '_inactive'
local section_redirects = {
lualine_x = 'lualine_c',
lualine_y = 'lualine_b',
lualine_z = 'lualine_a',
}
if section_redirects[section] then
section = highlight.highlight_exists(section .. suffix) and section or section_redirects[section]
end
return section .. suffix
end
function M:init(options)
M.super.init(self, options)
-- if use_mode_colors is set, use a function so that the colors update
local default_active = options.use_mode_colors
and function()
return get_hl('lualine_' .. options.self.section, true)
end
or get_hl('lualine_' .. options.self.section, true)
default_options.tabs_color = {
active = default_active,
inactive = get_hl('lualine_' .. options.self.section, false),
}
self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
-- stylua: ignore
self.highlights = {
active = self:create_hl(self.options.tabs_color.active, 'active'),
inactive = self:create_hl(self.options.tabs_color.inactive, 'inactive'),
}
end
function M:update_status()
local data = {}
local tabs = {}
for nr, id in ipairs(vim.api.nvim_list_tabpages()) do
tabs[#tabs + 1] = Tab { tabId = id, tabnr = nr, options = self.options, highlights = self.highlights }
end
-- mark the first, last, current, before current, after current tabpages
-- for rendering
local current = vim.fn.tabpagenr()
tabs[1].first = true
tabs[#tabs].last = true
if tabs[current] then
tabs[current].current = true
end
if tabs[current - 1] then
tabs[current - 1].beforecurrent = true
end
if tabs[current + 1] then
tabs[current + 1].aftercurrent = true
end
local max_length = self.options.max_length
if type(max_length) == 'function' then
max_length = max_length(self)
end
if max_length == 0 then
max_length = math.floor(vim.o.columns / 3)
end
local total_length
for i, tab in pairs(tabs) do
if tab.current then
current = i
end
end
local current_tab = tabs[current]
-- start drawing from current tab and draw left and right of it until
-- all tabpages are drawn or max_length has been reached.
if current_tab == nil then -- maybe redundant code
local t = Tab {
tabId = vim.api.nvim_get_current_tabpage(),
tabnr = vim.fn.tabpagenr(),
options = self.options,
highlights = self.highlights,
}
t.current = true
t.last = true
data[#data + 1] = t:render()
else
data[#data + 1] = current_tab:render()
total_length = current_tab.len
local i = 0
local before, after
while true do
i = i + 1
before = tabs[current - i]
after = tabs[current + i]
local rendered_before, rendered_after
if before == nil and after == nil then
break
end
-- draw left most undrawn tab if fits in max_length
if before then
rendered_before = before:render()
total_length = total_length + before.len
if total_length > max_length then
break
end
table.insert(data, 1, rendered_before)
end
-- draw right most undrawn tab if fits in max_length
if after then
rendered_after = after:render()
total_length = total_length + after.len
if total_length > max_length then
break
end
data[#data + 1] = rendered_after
end
end
-- draw ellipsis (...) on relevant sides if all tabs don't fit in max_length
if total_length > max_length then
if before ~= nil then
before.ellipse = true
before.first = true
table.insert(data, 1, before:render())
end
if after ~= nil then
after.ellipse = true
after.last = true
data[#data + 1] = after:render()
end
end
end
return table.concat(data)
end
function M:draw()
self.status = ''
self.applied_separator = ''
if self.options.cond ~= nil and self.options.cond() ~= true then
return self.status
end
local status = self:update_status()
if type(status) == 'string' and #status > 0 then
self.status = status
self:apply_section_separators()
self:apply_separator()
end
return self.status
end
vim.cmd([[
function! LualineSwitchTab(tabnr, mouseclicks, mousebutton, modifiers)
execute a:tabnr . "tabnext"
endfunction
function! LualineRenameTab(...)
if a:0 == 1
let t:tabname = a:1
else
unlet t:tabname
end
redrawtabline
endfunction
command! -nargs=? LualineRenameTab call LualineRenameTab("<args>")
]])
return M

View File

@ -0,0 +1,178 @@
local Tab = require('lualine.utils.class'):extend()
local modules = require('lualine_require').lazy_require {
highlight = 'lualine.highlight',
utils = 'lualine.utils.utils',
}
---initialize a new tab from opts
---@param opts table
function Tab:init(opts)
assert(opts.tabnr, 'Cannot create Tab without tabnr')
self.tabnr = opts.tabnr
self.tabId = opts.tabId
self.options = opts.options
self.highlights = opts.highlights
self.modified_icon = ''
self:get_props()
end
function Tab:get_props()
local buflist = vim.fn.tabpagebuflist(self.tabnr)
local winnr = vim.fn.tabpagewinnr(self.tabnr)
local bufnr = buflist[winnr]
self.file = modules.utils.stl_escape(vim.api.nvim_buf_get_name(bufnr))
self.filetype = vim.api.nvim_buf_get_option(bufnr, 'filetype')
self.buftype = vim.api.nvim_buf_get_option(bufnr, 'buftype')
if self.options.show_modified_status then
for _, b in ipairs(buflist) do
if vim.api.nvim_buf_get_option(b, 'modified') then
self.modified_icon = self.options.symbols.modified or ''
break
end
end
end
end
---returns name for tab. Tabs name is the name of buffer in last active window
--- of the tab.
---@return string
function Tab:label()
local ok, custom_tabname = pcall(vim.api.nvim_tabpage_get_var, self.tabId, 'tabname')
if not ok then
custom_tabname = nil
end
if custom_tabname and custom_tabname ~= '' then
return modules.utils.stl_escape(custom_tabname)
end
if self.filetype == 'fugitive' then
return 'fugitive: ' .. vim.fn.fnamemodify(self.file, ':h:h:t')
elseif self.buftype == 'help' then
return 'help:' .. vim.fn.fnamemodify(self.file, ':t:r')
elseif self.buftype == 'terminal' then
local match = string.match(vim.split(self.file, ' ')[1], 'term:.*:(%a+)')
return match ~= nil and match or vim.fn.fnamemodify(vim.env.SHELL, ':t')
elseif self.file == '' then
return '[No Name]'
end
if self.options.path == 1 then
return vim.fn.fnamemodify(self.file, ':~:.')
elseif self.options.path == 2 then
return vim.fn.fnamemodify(self.file, ':p')
elseif self.options.path == 3 then
return vim.fn.fnamemodify(self.file, ':p:~')
else
return vim.fn.fnamemodify(self.file, ':t')
end
end
---shortens path by turning apple/orange -> a/orange
---@param path string
---@param sep string path separator
---@param max_len integer maximum length of the full filename string
---@return string
local function shorten_path(path, sep, max_len)
local len = #path
if len <= max_len then
return path
end
local segments = vim.split(path, sep)
for idx = 1, #segments - 1 do
if len <= max_len then
break
end
local segment = segments[idx]
local shortened = segment:sub(1, vim.startswith(segment, '.') and 2 or 1)
segments[idx] = shortened
len = len - (#segment - #shortened)
end
return table.concat(segments, sep)
end
---returns rendered tab
---@return string
function Tab:render()
local name = self:label()
if self.options.tab_max_length ~= 0 then
local path_separator = package.config:sub(1, 1)
name = shorten_path(name, path_separator, self.options.tab_max_length)
end
if self.options.fmt then
name = self.options.fmt(name or '', self)
end
if self.ellipse then -- show ellipsis
name = '...'
else
-- different formats for different modes
if self.options.mode == 0 then
name = tostring(self.tabnr)
if self.modified_icon ~= '' then
name = string.format('%s%s', name, self.modified_icon)
end
elseif self.options.mode == 1 then
if self.modified_icon ~= '' then
name = string.format('%s %s', self.modified_icon, name)
end
else
name = string.format('%s%s %s', tostring(self.tabnr), self.modified_icon, name)
end
end
name = Tab.apply_padding(name, self.options.padding)
self.len = vim.fn.strchars(name)
-- setup for mouse clicks
local line = string.format('%%%s@LualineSwitchTab@%s%%T', self.tabnr, name)
-- apply highlight
line = modules.highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')])
.. line
-- apply separators
if self.options.self.section < 'x' and not self.first then
local sep_before = self:separator_before()
line = sep_before .. line
self.len = self.len + vim.fn.strchars(sep_before)
elseif self.options.self.section >= 'x' and not self.last then
local sep_after = self:separator_after()
line = line .. sep_after
self.len = self.len + vim.fn.strchars(sep_after)
end
return line
end
---apply separator before current tab
---@return string
function Tab:separator_before()
if self.current or self.aftercurrent then
return '%Z{' .. self.options.section_separators.left .. '}'
else
return self.options.component_separators.left
end
end
---apply separator after current tab
---@return string
function Tab:separator_after()
if self.current or self.beforecurrent then
return '%z{' .. self.options.section_separators.right .. '}'
else
return self.options.component_separators.right
end
end
---adds spaces to left and right
function Tab.apply_padding(str, padding)
local l_padding, r_padding = 1, 1
if type(padding) == 'number' then
l_padding, r_padding = padding, padding
elseif type(padding) == 'table' then
l_padding, r_padding = padding.left or 0, padding.right or 0
end
return string.rep(' ', l_padding) .. str .. string.rep(' ', r_padding)
end
return Tab

View File

@ -0,0 +1,64 @@
local Window = require('lualine.components.windows.window')
local M = require('lualine.components.buffers'):extend()
local default_options = {
disabled_filetypes = {},
disabled_buftypes = { 'quickfix', 'prompt' },
}
function M:init(options)
options.buffers_color = nil -- buffers_color isn't windows option.
M.super.init(self, options)
self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options)
self.options.windows_color = vim.tbl_deep_extend('keep', self.options.windows_color or {}, self.options.buffers_color)
self.options.buffers_color = nil -- this is the default value of colors generated by parent buffers component.
self.highlights = {
active = self:create_hl(self.options.windows_color.active, 'active'),
inactive = self:create_hl(self.options.windows_color.inactive, 'inactive'),
}
end
function M:new_buffer(winnr)
winnr = winnr or vim.api.nvim_get_current_win()
return Window:new {
winnr = winnr,
options = self.options,
highlights = self.highlights,
}
end
--- Override to only return buffers shown in the windows of the current tab
function M:buffers()
local tabnr = vim.api.nvim_get_current_tabpage()
local buffers = {}
for _, winnr in ipairs(vim.api.nvim_tabpage_list_wins(tabnr)) do
if not self:should_hide(winnr) then
buffers[#buffers + 1] = self:new_buffer(winnr)
end
end
return buffers
end
function M:should_hide(winnr)
local bufnr = vim.api.nvim_win_get_buf(winnr)
local filetype = vim.api.nvim_buf_get_option(bufnr, 'filetype')
local buftype = vim.api.nvim_buf_get_option(bufnr, 'buftype')
local is_filetype_disabled = vim.tbl_contains(self.options.disabled_filetypes, filetype)
local is_buftype_disabled = vim.tbl_contains(self.options.disabled_buftypes, buftype)
local is_floating = '' ~= vim.api.nvim_win_get_config(winnr).relative
return is_floating or is_buftype_disabled or is_filetype_disabled
end
vim.cmd([[
function! LualineSwitchWindow(win_number, mouseclicks, mousebutton, modifiers)
execute a:win_number . 'wincmd w'
endfunction
]])
return M

View File

@ -0,0 +1,35 @@
local Window = require('lualine.components.buffers.buffer'):extend()
---initialize a new buffer from opts
---@param opts table
function Window:init(opts)
assert(opts.winnr, 'Cannot create Window without winnr')
opts.bufnr = vim.api.nvim_win_get_buf(opts.winnr)
Window.super.init(self, opts)
self.winnr = opts.winnr
self.win_number = vim.api.nvim_win_get_number(self.winnr)
end
function Window:is_current()
return vim.api.nvim_get_current_win() == self.winnr
end
function Window:apply_mode(name)
if self.options.mode == 0 then
return string.format('%s%s%s', self.icon, name, self.modified_icon)
end
if self.options.mode == 1 then
return string.format('%s %s%s', self.win_number, self.icon, self.modified_icon)
end
return string.format('%s %s%s%s', self.win_number, self.icon, name, self.modified_icon)
end
function Window:configure_mouse_click(name)
return string.format('%%%s@LualineSwitchWindow@%s%%T', self.win_number, name)
end
return Window

View File

@ -0,0 +1,135 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local require = require('lualine_require').require
local utils = require('lualine.utils.utils')
local modules = require('lualine_require').lazy_require {
utils_notices = 'lualine.utils.notices',
}
local config = {
options = {
icons_enabled = true,
theme = 'auto',
component_separators = { left = '', right = '' },
section_separators = { left = '', right = '' },
disabled_filetypes = {
statusline = {},
winbar = {},
},
ignore_focus = {},
always_divide_middle = true,
globalstatus = vim.go.laststatus == 3,
refresh = {
statusline = 1000,
tabline = 1000,
winbar = 1000,
},
},
sections = {
lualine_a = { 'mode' },
lualine_b = { 'branch', 'diff', 'diagnostics' },
lualine_c = { 'filename' },
lualine_x = { 'encoding', 'fileformat', 'filetype' },
lualine_y = { 'progress' },
lualine_z = { 'location' },
},
inactive_sections = {
lualine_a = {},
lualine_b = {},
lualine_c = { 'filename' },
lualine_x = { 'location' },
lualine_y = {},
lualine_z = {},
},
tabline = {},
winbar = {},
inactive_winbar = {},
extensions = {},
}
--- change separator format 'x' to {left='x', right='x'}
---@param separators string|table
---@return table
local function fix_separators(separators)
if separators ~= nil then
if type(separators) == 'string' then
return { left = separators, right = separators }
end
end
return separators
end
---copy raw disabled_filetypes to inner statusline & winbar tables.
---@param disabled_filetypes table
---@return table
local function fix_disabled_filetypes(disabled_filetypes)
if disabled_filetypes == nil then
return
end
if disabled_filetypes.statusline == nil then
disabled_filetypes.statusline = {}
end
if disabled_filetypes.winbar == nil then
disabled_filetypes.winbar = {}
end
for k, disabled_ft in ipairs(disabled_filetypes) do
table.insert(disabled_filetypes.statusline, disabled_ft)
table.insert(disabled_filetypes.winbar, disabled_ft)
disabled_filetypes[k] = nil
end
return disabled_filetypes
end
---extends config based on config_table
---@param config_table table
---@return table copy of config
local function apply_configuration(config_table)
if not config_table then
return utils.deepcopy(config)
end
local function parse_sections(section_group_name)
if config_table[section_group_name] == nil then
return
end
if not next(config_table[section_group_name]) then
config[section_group_name] = {}
return
end
for section_name, section in pairs(config_table[section_group_name]) do
if section_name == 'refresh' then
config[section_group_name][section_name] =
vim.tbl_deep_extend('force', config[section_group_name][section_name], utils.deepcopy(section))
else
config[section_group_name][section_name] = utils.deepcopy(section)
end
end
end
if vim.fn.has('nvim-0.8') == 0 and (next(config_table.winbar or {}) or next(config_table.inactive_winbar or {})) then
modules.utils_notices.add_notice('### winbar\nSorry `winbar can only be used in neovim 0.8 or higher.\n')
config_table.winbar = {}
config_table.inactive_winbar = {}
end
parse_sections('options')
parse_sections('sections')
parse_sections('inactive_sections')
parse_sections('tabline')
parse_sections('winbar')
parse_sections('inactive_winbar')
if config_table.extensions then
config.extensions = utils.deepcopy(config_table.extensions)
end
config.options.section_separators = fix_separators(config.options.section_separators)
config.options.component_separators = fix_separators(config.options.component_separators)
config.options.disabled_filetypes = fix_disabled_filetypes(config.options.disabled_filetypes)
return utils.deepcopy(config)
end
--- returns current active config
---@return table a copy of config
local function get_current_config()
return utils.deepcopy(config)
end
return {
get_config = get_current_config,
apply_configuration = apply_configuration,
}

View File

@ -0,0 +1,9 @@
-- MIT license, see LICENSE for more details.
-- Extension for aerial.nvim
local M = {}
M.sections = { lualine_a = { 'filetype' } }
M.filetypes = { 'aerial' }
return M

View File

@ -0,0 +1,11 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local nerdtree = require('lualine.extensions.nerdtree')
local M = {}
M.sections = vim.deepcopy(nerdtree.sections)
M.filetypes = { 'CHADTree' }
return M

View File

@ -0,0 +1,20 @@
local M = {}
M.sections = {
lualine_a = {
function()
return vim.fn['ctrlspace#context#Configuration']().Symbols.CS
end,
},
lualine_b = { 'ctrlspace#api#StatuslineModeSegment' },
lualine_y = { 'ctrlspace#api#StatuslineTabSegment' },
lualine_z = {
function()
return 'CtrlSpace'
end,
},
}
M.filetypes = { 'ctrlspace' }
return M

View File

@ -0,0 +1,11 @@
-- MIT license, see LICENSE for more details.
-- Extension for fern file explorer.
local nerdtree = require('lualine.extensions.nerdtree')
local M = {}
M.sections = vim.deepcopy(nerdtree.sections)
M.filetypes = { 'fern' }
return M

View File

@ -0,0 +1,17 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local M = {}
local function fugitive_branch()
local icon = '' -- e0a0
return icon .. ' ' .. vim.fn.FugitiveHead()
end
M.sections = {
lualine_a = { fugitive_branch },
lualine_z = { 'location' },
}
M.filetypes = { 'fugitive' }
return M

View File

@ -0,0 +1,45 @@
--[[
lualine extension for fzf filetypes:
works with both https://github.com/junegunn/fzf.vim and https://github.com/ibhagwan/fzf-lua
-- fzf-lua must be set-up in split mode
]]
local function has_fzf()
return pcall(require, 'fzf-lua')
end
local function fzf_picker()
if not has_fzf() then
return ''
end
local info_string = vim.inspect(require('fzf-lua').get_info()['fnc'])
return info_string:gsub('"', '')
end
local function fzf_element()
if not has_fzf() then
return ''
end
local fzf = require('fzf-lua')
local selected = fzf.get_info().selected
return fzf.path.entry_to_file(selected).path
end
local function fzf_statusline()
return 'FZF'
end
local M = {}
M.sections = {
lualine_a = { fzf_statusline },
lualine_y = { fzf_element },
lualine_z = { fzf_picker },
}
M.filetypes = { 'fzf' }
return M

View File

@ -0,0 +1,31 @@
-- lualine extension for lazy.nvim
local ok, lazy = pcall(require, 'lazy')
if not ok then
return ''
end
local M = {}
M.sections = {
lualine_a = {
function()
return 'lazy 💤'
end,
},
lualine_b = {
function()
return 'loaded: ' .. lazy.stats().loaded .. '/' .. lazy.stats().count
end,
},
lualine_c = {
{
require('lazy.status').updates,
cond = require('lazy.status').has_updates,
},
},
}
M.filetypes = { 'lazy' }
return M

View File

@ -0,0 +1,16 @@
local M = {}
M.sections = {
lualine_a = {
function()
return 'MAN'
end,
},
lualine_b = { { 'filename', file_status = false } },
lualine_y = { 'progress' },
lualine_z = { 'location' },
}
M.filetypes = { 'man' }
return M

View File

@ -0,0 +1,29 @@
-- lualine extension for mason.nvim
local mason_registry
local function maybe_set_registry()
local ok, registry = pcall(require, 'mason-registry')
if ok then
mason_registry = registry
end
end
local M = {}
M.sections = {
lualine_a = {
function()
return 'Mason'
end,
},
lualine_b = {
function()
maybe_set_registry()
return 'Installed: ' .. #mason_registry.get_installed_packages() .. '/' .. #mason_registry.get_all_package_specs()
end,
},
}
M.filetypes = { 'mason' }
return M

View File

@ -0,0 +1,19 @@
local M = {}
M.sections = {
lualine_a = {
function()
local ft = vim.opt_local.filetype:get()
return (ft == 'Mundo') and 'Change tree' or (ft == 'MundoDiff') and 'Change diff'
end,
},
lualine_y = { 'progress' },
lualine_z = { 'location' },
}
M.filetypes = {
'Mundo',
'MundoDiff',
}
return M

View File

@ -0,0 +1,11 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local nerdtree = require('lualine.extensions.nerdtree')
local M = {}
M.sections = vim.deepcopy(nerdtree.sections)
M.filetypes = { 'neo-tree' }
return M

View File

@ -0,0 +1,15 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local function get_short_cwd()
return vim.fn.fnamemodify(vim.fn.getcwd(), ':~')
end
local M = {}
M.sections = {
lualine_a = { get_short_cwd },
}
M.filetypes = { 'nerdtree' }
return M

View File

@ -0,0 +1,18 @@
-- MIT license, see LICENSE for more details.
-- Extension for nvim-dap-ui
local M = {}
M.sections = {
lualine_a = { { 'filename', file_status = false } },
}
M.filetypes = {
'dap-repl',
'dapui_console',
'dapui_watches',
'dapui_stacks',
'dapui_breakpoints',
'dapui_scopes',
}
return M

View File

@ -0,0 +1,11 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local nerdtree = require('lualine.extensions.nerdtree')
local M = {}
M.sections = vim.deepcopy(nerdtree.sections)
M.filetypes = { 'NvimTree' }
return M

View File

@ -0,0 +1,20 @@
-- Extension for oil.nvim
local M = {}
M.sections = {
lualine_a = {
function()
local ok, oil = pcall(require, 'oil')
if ok then
return vim.fn.fnamemodify(oil.get_current_dir(), ':~')
else
return ''
end
end,
},
}
M.filetypes = { 'oil' }
return M

View File

@ -0,0 +1,16 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local M = {}
M.sections = {
lualine_a = {
function()
return 'OverseerList'
end,
},
}
M.filetypes = { 'OverseerList' }
return M

View File

@ -0,0 +1,34 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
--
local function is_loclist()
return vim.fn.getloclist(0, { filewinid = 1 }).filewinid ~= 0
end
local function label()
return is_loclist() and 'Location List' or 'Quickfix List'
end
local function title()
if is_loclist() then
return vim.fn.getloclist(0, { title = 0 }).title
end
return vim.fn.getqflist({ title = 0 }).title
end
local M = {}
function M.init()
-- Make sure ft wf doesn't create a custom statusline
vim.g.qf_disable_statusline = true
end
M.sections = {
lualine_a = { label },
lualine_b = { title },
lualine_z = { 'location' },
}
M.filetypes = { 'qf' }
return M

View File

@ -0,0 +1,9 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local M = {}
M.sections = { lualine_a = { 'filetype' } }
M.filetypes = { 'Outline' }
return M

View File

@ -0,0 +1,16 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local function toggleterm_statusline()
return 'ToggleTerm #' .. vim.b.toggle_number
end
local M = {}
M.sections = {
lualine_a = { toggleterm_statusline },
}
M.filetypes = { 'toggleterm' }
return M

View File

@ -0,0 +1,22 @@
local M = {}
local function get_trouble_mode()
local opts = require('trouble.config').options
local words = vim.split(opts.mode, '[%W]')
for i, word in ipairs(words) do
words[i] = word:sub(1, 1):upper() .. word:sub(2)
end
return table.concat(words, ' ')
end
M.sections = {
lualine_a = {
get_trouble_mode,
},
}
M.filetypes = { 'Trouble' }
return M

View File

@ -0,0 +1,494 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local M = {}
local lualine_require = require('lualine_require')
local require = lualine_require.require
local modules = lualine_require.lazy_require {
utils = 'lualine.utils.utils',
color_utils = 'lualine.utils.color_utils',
}
local section_highlight_map = { x = 'c', y = 'b', z = 'a' }
local active_theme = nil
local theme_hls = {}
local create_cterm_colors = false
-- table to store the highlight names created by lualine
local loaded_highlights = {}
-- table to map mode to highlight suffixes
local mode_to_highlight = {
['VISUAL'] = '_visual',
['V-BLOCK'] = '_visual',
['V-LINE'] = '_visual',
['SELECT'] = '_visual',
['S-LINE'] = '_visual',
['S-BLOCK'] = '_visual',
['REPLACE'] = '_replace',
['V-REPLACE'] = '_replace',
['INSERT'] = '_insert',
['COMMAND'] = '_command',
['EX'] = '_command',
['MORE'] = '_command',
['CONFIRM'] = '_command',
['TERMINAL'] = '_terminal',
}
--- Get highlight suffix for current mode, or inactive if not focused
---@return string mode_suffix
function M.get_mode_suffix()
local mode = require('lualine.utils.mode').get_mode()
return mode_to_highlight[mode] or '_normal'
end
--- determine if an highlight exist and isn't cleared
---@param highlight_name string
---@return boolean whether hl_group was defined with highlight_name
function M.highlight_exists(highlight_name)
return loaded_highlights[highlight_name] or false
end
--- clears loaded_highlights table and highlights
local function clear_highlights()
for highlight_name, _ in pairs(loaded_highlights) do
vim.cmd('highlight clear ' .. highlight_name)
end
loaded_highlights = {}
end
---converts cterm, color_name type colors to #rrggbb format
---@param color string|number
---@return string
local function sanitize_color(color)
if color == nil or color == '' or (type(color) == 'string' and color:lower() == 'none') then
return 'None'
end
if type(color) == 'string' then
if color:sub(1, 1) == '#' then
return color
end -- RGB value
return modules.color_utils.color_name2rgb(color)
elseif type(color) == 'number' then
if color > 255 then
error("What's this it can't be higher then 255 and you've given " .. color)
end
return modules.color_utils.cterm2rgb(color)
end
end
---converts color_name type colors to cterm format and let cterm color pass through
---@param color string|number
---@return string
local function sanitize_color_for_cterm(color)
if type(color) == 'number' then
if color > 255 then
error("What's this it can't be higher then 255 and you've given " .. color)
end
return color
end
return modules.color_utils.rgb2cterm(sanitize_color(color))
end
function M.get_lualine_hl(name)
local hl = loaded_highlights[name]
if hl and not hl.empty then
if hl.link then
return modules.utils.extract_highlight_colors(hl.link)
end
local hl_def = {
fg = hl.fg ~= 'None' and vim.deepcopy(hl.fg) or nil,
bg = hl.bg ~= 'None' and vim.deepcopy(hl.bg) or nil,
sp = hl.sp ~= 'None' and vim.deepcopy(hl.sp) or nil,
}
if hl.gui then
for _, flag in ipairs(vim.split(hl.gui, ',')) do
if flag ~= 'None' then
hl_def[flag] = true
end
end
end
return hl_def
end
end
--- Define a hl_group
---@param name string
---@param foreground string|number: color
---@param background string|number: color
---@param gui table cterm/gui options like bold/italic etc.
---@param link string hl_group name to link new hl to
function M.highlight(name, foreground, background, gui, link)
local command = { 'highlight!' }
if link and #link > 0 then
if loaded_highlights[name] and loaded_highlights[name].link == link then
return
end
vim.list_extend(command, { 'link', name, link })
else
local foreground_rgb = sanitize_color(foreground)
local background_rgb = sanitize_color(background)
gui = (gui ~= nil and gui ~= '') and gui or 'None'
if
loaded_highlights[name]
and loaded_highlights[name].fg == foreground_rgb
and loaded_highlights[name].bg == background_rgb
and loaded_highlights[name].gui == gui
then
return -- color is already defined why are we doing this anyway ?
end
table.insert(command, name)
table.insert(command, 'guifg=' .. foreground_rgb)
table.insert(command, 'guibg=' .. background_rgb)
table.insert(command, 'gui=' .. gui)
if create_cterm_colors then
-- Not setting color from xxxground_rgb to let possible user 256 number through
table.insert(command, 'ctermfg=' .. sanitize_color_for_cterm(foreground))
table.insert(command, 'ctermbg=' .. sanitize_color_for_cterm(background))
table.insert(command, 'cterm=' .. gui)
end
end
vim.cmd(table.concat(command, ' '))
-- update attached hl groups
local old_hl_def = loaded_highlights[name]
if old_hl_def and next(old_hl_def.attached) then
-- Update attached hl groups as they announced to depend on hl_group 'name'
-- 'hl' being in 'name's attached table means 'hl'
-- depends of 'name'.
-- 'hl' key in attached table will contain a table that
-- defines the relation between 'hl' & 'name'.
-- name.attached.hl = { bg = 'fg' } means
-- hl's fg is same as 'names' bg . So 'hl's fg should
-- be updated when ever 'name' changes it's 'bg'
local bg_changed = old_hl_def.bg ~= background
local fg_changed = old_hl_def.bg ~= foreground
local gui_changed = old_hl_def.gui ~= gui
for attach_name, attach_desc in pairs(old_hl_def.attached) do
if bg_changed and attach_desc.bg and loaded_highlights[attach_name] then
M.highlight(
attach_name,
attach_desc.bg == 'fg' and background or loaded_highlights[attach_name].fg,
attach_desc.bg == 'bg' and background or loaded_highlights[attach_name].bg,
loaded_highlights[attach_name].gui,
loaded_highlights[attach_name].link
)
end
if fg_changed and attach_desc.fg and loaded_highlights[attach_name] then
M.highlight(
attach_name,
attach_desc.fg == 'fg' and foreground or loaded_highlights[attach_name].fg,
attach_desc.fg == 'bg' and foreground or loaded_highlights[attach_name].bg,
loaded_highlights[attach_name].gui,
loaded_highlights[attach_name].link
)
end
if gui_changed and attach_desc.gui and loaded_highlights[attach_name] then
M.highlight(
attach_name,
loaded_highlights[attach_name].fg,
loaded_highlights[attach_name].bg,
gui,
loaded_highlights[attach_name].link
)
end
end
end
-- store current hl state
loaded_highlights[name] = {
fg = foreground,
bg = background,
gui = gui,
link = link,
attached = old_hl_def and old_hl_def.attached or {},
}
end
---Attach a hl to another, so the attached auto updates on change to hl that it's attached too.
---@param provider string the hl receiver is getting attached to
---@param receiver string the hl that will be auto updated upon change to provider
---@param provider_el_type string (fg/bg) what element receiver relates to of provider
---@param receiver_el_type string (fg/bg) what element provider relates to of receiver
local function attach_hl(provider, receiver, provider_el_type, receiver_el_type)
if loaded_highlights[provider] == nil then
loaded_highlights[provider] = { empty = true, attached = {} }
end
loaded_highlights[provider].attached[receiver] = { [provider_el_type] = receiver_el_type }
end
---define hl_groups for a theme
---@param theme table
function M.create_highlight_groups(theme)
clear_highlights()
active_theme = theme
theme_hls = {}
local psudo_options = { self = { section = 'a' } }
create_cterm_colors = not vim.go.termguicolors
for mode, sections in pairs(theme) do
theme_hls[mode] = {}
for section, color in pairs(sections) do
local hl_tag = mode
psudo_options.self.section = section
theme_hls[mode][section] = M.create_component_highlight_group(color, hl_tag, psudo_options, true)
end
end
end
---@description: adds '_mode' at end of highlight_group
---@param highlight_group string name of highlight group
---@return string highlight group name with mode
local function append_mode(highlight_group, is_focused)
if is_focused == nil then
is_focused = modules.utils.is_focused()
end
if is_focused == false then
return highlight_group .. '_inactive'
end
return highlight_group .. M.get_mode_suffix()
end
-- Helper function for create component highlight
---Handles fall back of colors when creating highlight group
---@param hl_name string name of highlight that we are setting default values for
---@param mode string mode which default component color should be given.
---@param section string the lualine section component is in.
---@param color table color passed for creating component highlight
---@param options table Options table of component this is first fall back
local function get_default_component_color(hl_name, mode, section, color, options)
local default_theme_color
if active_theme[mode] and active_theme[mode][section] then
default_theme_color = active_theme[mode][section]
elseif section >= 'c' and active_theme[mode] and active_theme[mode][section_highlight_map[section]] then
default_theme_color = active_theme[mode][section_highlight_map[section]]
elseif section >= 'c' and active_theme.normal[section_highlight_map[section]] then
default_theme_color = active_theme.normal[section_highlight_map[section]]
else
default_theme_color = active_theme.normal[section]
end
local ret = { fg = color.fg, bg = color.bg, gui = color.gui }
if ret.fg and ret.bg then
return ret
end
local function apply_default(def_color, def_name)
if type(def_color) == 'function' and loaded_highlights[def_name] and not loaded_highlights[def_name].empty then
if loaded_highlights[def_name].link then
def_color = loaded_highlights[def_name].link
else
def_color = loaded_highlights[def_name]
end
end
if type(def_color) == 'function' then
def_color = def_color { section = section }
end
if type(def_color) == 'string' then
def_color = modules.utils.extract_highlight_colors(def_color)
end
if type(def_color) == 'table' then
if not ret.fg then
ret.fg = def_color.fg
attach_hl(def_name, hl_name, 'fg', 'fg')
end
if not ret.bg then
ret.bg = def_color.bg
attach_hl(def_name, hl_name, 'bg', 'bg')
end
end
end
if
options.color
and options.color_highlight
and options.color_highlight.name
and options.color_highlight.name .. '_' .. mode ~= hl_name
then
apply_default(options.color, options.color_highlight.name .. '_' .. mode)
end
if not ret.fg or not ret.bg then
apply_default(default_theme_color, string.format('lualine_%s_%s', section, mode))
end
ret.fg = sanitize_color(ret.fg)
ret.bg = sanitize_color(ret.bg)
return ret
end
---Create highlight group with fg bg and gui from theme
---@param color table has to be { fg = "#rrggbb", bg="#rrggbb" gui = "effect" }
--- all the color elements are optional if fg or bg is not given options
--- must be provided So fg and bg can default the themes colors
---@param highlight_tag string is unique tag for highlight group
---returns the name of highlight group
---@param options table is parameter of component.init() function
---@return table that can be used by component_format_highlight
--- to retrieve highlight group
function M.create_component_highlight_group(color, highlight_tag, options, apply_no_default)
local section = options.self.section
local tag_id = 0
while
M.highlight_exists(table.concat({ 'lualine', section, highlight_tag }, '_'))
or (section and M.highlight_exists(table.concat({ 'lualine', section, highlight_tag, 'normal' }, '_')))
do
highlight_tag = highlight_tag .. '_' .. tostring(tag_id)
tag_id = tag_id + 1
end
if type(color) == 'string' then
local highlight_group_name = table.concat({ 'lualine', section, highlight_tag }, '_')
M.highlight(highlight_group_name, nil, nil, nil, color) -- l8nk to group
return {
name = highlight_group_name,
fn = nil,
no_mode = true,
link = true,
section = section,
options = options,
no_default = apply_no_default,
}
end
if type(color) ~= 'function' and (apply_no_default or (color.bg and color.fg)) then
-- When bg and fg are both present we don't need to set highlights for
-- each mode as they will surely look the same. So we can work without options
local highlight_group_name = table.concat({ 'lualine', section, highlight_tag }, '_')
M.highlight(highlight_group_name, color.fg, color.bg, color.gui, nil)
return {
name = highlight_group_name,
fn = nil,
no_mode = true,
section = section,
options = options,
no_default = apply_no_default,
}
end
local modes = {
'normal',
'insert',
'visual',
'replace',
'command',
'terminal',
'inactive',
}
for _, mode in ipairs(modes) do
local hl_name = table.concat({ 'lualine', section, highlight_tag, mode }, '_')
local cl = color
if type(color) == 'function' then
cl = color { section = section } or {}
end
if type(cl) == 'string' then
cl = { link = cl }
else
cl = get_default_component_color(hl_name, mode, section, cl, options)
end
M.highlight(hl_name, cl.fg, cl.bg, cl.gui, cl.link)
end
return {
name = table.concat({ 'lualine', section, highlight_tag }, '_'),
fn = type(color) == 'function' and color,
no_mode = false,
link = false,
section = section,
options = options,
no_default = apply_no_default,
}
end
---@description: retrieve highlight_groups for components
---@param highlight table return value of create_component_highlight_group
--- return value of create_component_highlight_group is to be passed in
--- this parameter to receive highlight that was created
---@return string formatted highlight group name
function M.component_format_highlight(highlight, is_focused)
if not highlight.fn then
local highlight_group = highlight.name
if highlight.no_mode then
return '%#' .. highlight_group .. '#'
end
highlight_group = append_mode(highlight_group, is_focused)
return '%#' .. highlight_group .. '#'
else
local color = highlight.fn { section = highlight.section } or {}
local hl_name = highlight.name
if type(color) == 'string' then
M.highlight(hl_name .. M.get_mode_suffix(), nil, nil, nil, color)
return '%#' .. hl_name .. M.get_mode_suffix() .. '#'
elseif type(color) == 'table' then
if not highlight.no_default and not (color.fg and color.bg) then
hl_name = append_mode(highlight.name, is_focused)
color =
get_default_component_color(hl_name, M.get_mode_suffix():sub(2), highlight.section, color, highlight.options)
end
M.highlight(hl_name, color.fg, color.bg, color.gui, color.link)
return '%#' .. hl_name .. '#', color
end
end
end
---@description: retrieve highlight_groups for section
---@param section string highlight group name without mode
--- return value of create_component_highlight_group is to be passed in
--- this parameter to receive highlight that was created
---@param is_focused boolean
---@return string formatted highlight group name
function M.format_highlight(section, is_focused)
local mode = append_mode('', is_focused):sub(2)
local ret = ''
if theme_hls[mode] and theme_hls[mode][section] then
ret = M.component_format_highlight(theme_hls[mode][section], is_focused)
elseif theme_hls[mode] and section > 'c' and theme_hls[mode][section_highlight_map[section]] then
ret = M.component_format_highlight(theme_hls[mode][section_highlight_map[section]], is_focused)
elseif theme_hls['normal'] and theme_hls['normal'][section] then
ret = M.component_format_highlight(theme_hls['normal'][section], is_focused)
elseif theme_hls['normal'] and section > 'c' and theme_hls['normal'][section_highlight_map[section]] then
ret = M.component_format_highlight(theme_hls['normal'][section_highlight_map[section]], is_focused)
end
return ret
end
---@description : Provides transitional highlights for section separators.
---@param left_hl string this highlights bg is used for fg of transitional hl
---@param right_hl string this highlights bg is used for bg of transitional hl
--- '▶️' and '◀️' ' needs reverse colors so the caller should swap left and right
---@return string formatted highlight group name
function M.get_transitional_highlights(left_hl, right_hl)
-- When both left and right highlights are same or one is absent
-- nothing to transition to.
if left_hl == nil or right_hl == nil or left_hl == right_hl then
return nil
end
-- construct the name of highlight group
local highlight_name = table.concat({ 'lualine_transitional', left_hl, 'to', right_hl }, '_')
if not M.highlight_exists(highlight_name) then
-- Create the highlight_group if needed
-- Get colors from highlights
local fg = modules.utils.extract_highlight_colors(left_hl, 'bg')
local bg = modules.utils.extract_highlight_colors(right_hl, 'bg')
if not fg and not bg then
return nil -- Color retrieval failed
end
if bg == fg then
return nil -- Separator won't be visible anyway
end
M.highlight(highlight_name, fg, bg, nil, nil)
attach_hl(left_hl, highlight_name, 'bg', 'fg')
attach_hl(right_hl, highlight_name, 'bg', 'bg')
end
return '%#' .. highlight_name .. '#'
end
function M.get_stl_default_hl(focused)
if focused == 3 then
return 'TabLineFill'
elseif not focused then
return 'StatusLineNC'
else
return 'StatusLine'
end
end
return M

View File

@ -0,0 +1,38 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit itchyny, jackno (lightline)
-- stylua: ignore
local colors = {
black = '#000000',
maroon = '#800000',
green = '#008000',
olive = '#808000',
navy = '#000080',
purple = '#800080',
teal = '#008080',
silver = '#c0c0c0',
gray = '#808080',
red = '#ff0000',
lime = '#00ff00',
yellow = '#ffff00',
blue = '#0000ff',
fuchsia = '#ff00ff',
aqua = '#00ffff',
white = '#ffffff',
}
return {
normal = {
a = { fg = colors.white, bg = colors.blue, gui = 'bold' },
b = { fg = colors.white, bg = colors.gray },
c = { fg = colors.silver, bg = colors.black },
},
insert = { a = { fg = colors.white, bg = colors.green, gui = 'bold' } },
visual = { a = { fg = colors.white, bg = colors.purple, gui = 'bold' } },
replace = { a = { fg = colors.white, bg = colors.red, gui = 'bold' } },
inactive = {
a = { fg = colors.silver, bg = colors.gray, gui = 'bold' },
b = { fg = colors.gray, bg = colors.black },
c = { fg = colors.silver, bg = colors.black },
},
}

View File

@ -0,0 +1,43 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Generated by lightline to lualine theme converter
-- https://gist.github.com/shadmansaleh/000871c9a608a012721c6acc6d7a19b9
-- stylua: ignore
local colors = {
color0 = '#ffffff',
color1 = '#99c794',
color2 = '#65737e',
color3 = '#343d46',
color4 = '#6699cc',
color5 = '#d8dee9',
color6 = '#f99157',
color7 = '#ec5f67',
}
return {
insert = {
a = { fg = colors.color0, bg = colors.color1, gui = 'bold' },
b = { fg = colors.color0, bg = colors.color2 },
c = { fg = colors.color0, bg = colors.color3 },
},
normal = {
a = { fg = colors.color0, bg = colors.color4, gui = 'bold' },
b = { fg = colors.color0, bg = colors.color2 },
c = { fg = colors.color0, bg = colors.color3 },
},
inactive = {
a = { fg = colors.color5, bg = colors.color2, gui = 'bold' },
b = { fg = colors.color5, bg = colors.color3 },
c = { fg = colors.color2, bg = colors.color3 },
},
visual = {
a = { fg = colors.color0, bg = colors.color6, gui = 'bold' },
b = { fg = colors.color0, bg = colors.color2 },
c = { fg = colors.color0, bg = colors.color3 },
},
replace = {
a = { fg = colors.color0, bg = colors.color7, gui = 'bold' },
b = { fg = colors.color0, bg = colors.color2 },
c = { fg = colors.color0, bg = colors.color3 },
},
}

View File

@ -0,0 +1,6 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: itchyny(lightline)
local background = vim.opt.background:get()
return require('lualine.themes.papercolor_' .. background)

View File

@ -0,0 +1,43 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Generated by lightline to lualine theme converter
-- https://gist.github.com/shadmansaleh/000871c9a608a012721c6acc6d7a19b9
-- stylua: ignore
local colors = {
color14 = '#718c00',
color0 = '#666666',
color1 = '#c8c8c8',
color2 = '#808080',
color3 = '#fafafa',
color4 = '#4271ae',
color5 = '#4d4d4c',
color6 = '#b4b4b4',
color7 = '#555555',
color8 = '#8959a8',
color11 = '#f5871f',
}
return {
inactive = {
a = { fg = colors.color0, bg = colors.color1, gui = 'bold' },
b = { fg = colors.color2, bg = colors.color3 },
c = { fg = colors.color0, bg = colors.color1 },
},
normal = {
a = { fg = colors.color1, bg = colors.color4, gui = 'bold' },
b = { fg = colors.color5, bg = colors.color6 },
c = { fg = colors.color7, bg = colors.color1 },
},
visual = {
a = { fg = colors.color1, bg = colors.color8, gui = 'bold' },
b = { fg = colors.color5, bg = colors.color6 },
},
replace = {
a = { fg = colors.color1, bg = colors.color11, gui = 'bold' },
b = { fg = colors.color5, bg = colors.color6 },
},
insert = {
a = { fg = colors.color1, bg = colors.color14, gui = 'bold' },
b = { fg = colors.color5, bg = colors.color6 },
},
}

View File

@ -0,0 +1,172 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local utils = require('lualine.utils.utils')
local loader = require('lualine.utils.loader')
local color_name = vim.g.colors_name
if color_name then
-- All base16 colorschemes share the same theme
if 'base16' == color_name:sub(1, 6) then
color_name = 'base16'
end
-- Check if there's a theme for current colorscheme
-- If there is load that instead of generating a new one
local ok, theme = pcall(loader.load_theme, color_name)
if ok and theme then
return theme
end
end
---------------
-- Constants --
---------------
-- fg and bg must have this much contrast range 0 < contrast_threshold < 0.5
local contrast_threshold = 0.3
-- how much brightness is changed in percentage for light and dark themes
local brightness_modifier_parameter = 10
-- Turns #rrggbb -> { red, green, blue }
local function rgb_str2num(rgb_color_str)
if rgb_color_str:find('#') == 1 then
rgb_color_str = rgb_color_str:sub(2, #rgb_color_str)
end
local red = tonumber(rgb_color_str:sub(1, 2), 16)
local green = tonumber(rgb_color_str:sub(3, 4), 16)
local blue = tonumber(rgb_color_str:sub(5, 6), 16)
return { red = red, green = green, blue = blue }
end
-- Turns { red, green, blue } -> #rrggbb
local function rgb_num2str(rgb_color_num)
local rgb_color_str = string.format('#%02x%02x%02x', rgb_color_num.red, rgb_color_num.green, rgb_color_num.blue)
return rgb_color_str
end
-- Returns brightness level of color in range 0 to 1
-- arbitrary value it's basically an weighted average
local function get_color_brightness(rgb_color)
local color = rgb_str2num(rgb_color)
local brightness = (color.red * 2 + color.green * 3 + color.blue) / 6
return brightness / 256
end
-- returns average of colors in range 0 to 1
-- used to determine contrast level
local function get_color_avg(rgb_color)
local color = rgb_str2num(rgb_color)
return (color.red + color.green + color.blue) / 3 / 256
end
-- Clamps the val between left and right
local function clamp(val, left, right)
if val > right then
return right
end
if val < left then
return left
end
return val
end
-- Changes brightness of rgb_color by percentage
local function brightness_modifier(rgb_color, percentage)
local color = rgb_str2num(rgb_color)
color.red = clamp(color.red + (color.red * percentage / 100), 0, 255)
color.green = clamp(color.green + (color.green * percentage / 100), 0, 255)
color.blue = clamp(color.blue + (color.blue * percentage / 100), 0, 255)
return rgb_num2str(color)
end
-- Changes contrast of rgb_color by amount
local function contrast_modifier(rgb_color, amount)
local color = rgb_str2num(rgb_color)
color.red = clamp(color.red + amount, 0, 255)
color.green = clamp(color.green + amount, 0, 255)
color.blue = clamp(color.blue + amount, 0, 255)
return rgb_num2str(color)
end
-- Changes brightness of foreground color to achieve contrast
-- without changing the color
local function apply_contrast(highlight)
local highlight_bg_avg = get_color_avg(highlight.bg)
local contrast_threshold_config = clamp(contrast_threshold, 0, 0.5)
local contrast_change_step = 5
if highlight_bg_avg > 0.5 then
contrast_change_step = -contrast_change_step
end
-- Don't waste too much time here max 25 iteration should be more than enough
local iteration_count = 1
while math.abs(get_color_avg(highlight.fg) - highlight_bg_avg) < contrast_threshold_config and iteration_count < 25 do
highlight.fg = contrast_modifier(highlight.fg, contrast_change_step)
iteration_count = iteration_count + 1
end
end
-- Get the colors to create theme
-- stylua: ignore
local colors = {
normal = utils.extract_color_from_hllist('bg', { 'PmenuSel', 'PmenuThumb', 'TabLineSel' }, '#000000'),
insert = utils.extract_color_from_hllist('fg', { 'String', 'MoreMsg' }, '#000000'),
replace = utils.extract_color_from_hllist('fg', { 'Number', 'Type' }, '#000000'),
visual = utils.extract_color_from_hllist('fg', { 'Special', 'Boolean', 'Constant' }, '#000000'),
command = utils.extract_color_from_hllist('fg', { 'Identifier' }, '#000000'),
back1 = utils.extract_color_from_hllist('bg', { 'Normal', 'StatusLineNC' }, '#000000'),
fore = utils.extract_color_from_hllist('fg', { 'Normal', 'StatusLine' }, '#000000'),
back2 = utils.extract_color_from_hllist('bg', { 'StatusLine' }, '#000000'),
}
-- Change brightness of colors
-- Darken if light theme (or) Lighten if dark theme
local normal_color = utils.extract_highlight_colors('Normal', 'bg')
if normal_color ~= nil then
if get_color_brightness(normal_color) > 0.5 then
brightness_modifier_parameter = -brightness_modifier_parameter
end
for name, color in pairs(colors) do
colors[name] = brightness_modifier(color, brightness_modifier_parameter)
end
end
-- Basic theme definition
local M = {
normal = {
a = { bg = colors.normal, fg = colors.back1, gui = 'bold' },
b = { bg = colors.back1, fg = colors.normal },
c = { bg = colors.back2, fg = colors.fore },
},
insert = {
a = { bg = colors.insert, fg = colors.back1, gui = 'bold' },
b = { bg = colors.back1, fg = colors.insert },
c = { bg = colors.back2, fg = colors.fore },
},
replace = {
a = { bg = colors.replace, fg = colors.back1, gui = 'bold' },
b = { bg = colors.back1, fg = colors.replace },
c = { bg = colors.back2, fg = colors.fore },
},
visual = {
a = { bg = colors.visual, fg = colors.back1, gui = 'bold' },
b = { bg = colors.back1, fg = colors.visual },
c = { bg = colors.back2, fg = colors.fore },
},
command = {
a = { bg = colors.command, fg = colors.back1, gui = 'bold' },
b = { bg = colors.back1, fg = colors.command },
c = { bg = colors.back2, fg = colors.fore },
},
}
M.terminal = M.command
M.inactive = M.normal
-- Apply proper contrast so text is readable
for _, section in pairs(M) do
for _, highlight in pairs(section) do
apply_contrast(highlight)
end
end
return M

View File

@ -0,0 +1,8 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: itchyny(lightline)
-- License: MIT License
local background = vim.opt.background:get()
local style = vim.g.ayucolor or ((background == 'dark') and vim.g.ayuprefermirage and 'mirage' or background)
return require('lualine.themes.ayu_' .. style)

View File

@ -0,0 +1,40 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Generated by lightline to lualine theme converter
-- https://gist.github.com/shadmansaleh/000871c9a608a012721c6acc6d7a19b9
-- stylua: ignore
local colors = {
color2 = '#0f1419',
color3 = '#ffee99',
color4 = '#e6e1cf',
color5 = '#14191f',
color13 = '#b8cc52',
color10 = '#36a3d9',
color8 = '#f07178',
color9 = '#3e4b59',
}
return {
visual = {
a = { fg = colors.color2, bg = colors.color3, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
replace = {
a = { fg = colors.color2, bg = colors.color8, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
inactive = {
c = { fg = colors.color4, bg = colors.color2 },
a = { fg = colors.color4, bg = colors.color5, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
normal = {
c = { fg = colors.color9, bg = colors.color2 },
a = { fg = colors.color2, bg = colors.color10, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
insert = {
a = { fg = colors.color2, bg = colors.color13, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
}

View File

@ -0,0 +1,40 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Generated by lightline to lualine theme converter
-- https://gist.github.com/shadmansaleh/000871c9a608a012721c6acc6d7a19b9
-- stylua: ignore
local colors = {
color2 = '#f3f3f3',
color3 = '#A37ACC',
color4 = '#5C6773',
color5 = '#d3d3d3',
color13 = '#86B300',
color10 = '#59c2ff',
color8 = '#f07178',
color9 = '#828C99',
}
return {
visual = {
a = { fg = colors.color2, bg = colors.color3, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
replace = {
a = { fg = colors.color2, bg = colors.color8, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
inactive = {
c = { fg = colors.color4, bg = colors.color2 },
a = { fg = colors.color4, bg = colors.color5, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
normal = {
c = { fg = colors.color9, bg = colors.color2 },
a = { fg = colors.color2, bg = colors.color10, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
insert = {
a = { fg = colors.color2, bg = colors.color13, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
}

View File

@ -0,0 +1,40 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Generated by lightline to lualine theme converter
-- https://gist.github.com/shadmansaleh/000871c9a608a012721c6acc6d7a19b9
-- stylua: ignore
local colors = {
color2 = '#242b38',
color3 = '#d4bfff',
color4 = '#d9d7ce',
color5 = '#272d38',
color13 = '#bbe67e',
color10 = '#59c2ff',
color8 = '#f07178',
color9 = '#607080',
}
return {
visual = {
a = { fg = colors.color2, bg = colors.color3, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
replace = {
a = { fg = colors.color2, bg = colors.color8, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
inactive = {
c = { fg = colors.color4, bg = colors.color2 },
a = { fg = colors.color4, bg = colors.color5, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
normal = {
c = { fg = colors.color9, bg = colors.color2 },
a = { fg = colors.color2, bg = colors.color10, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
insert = {
a = { fg = colors.color2, bg = colors.color13, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
}

View File

@ -0,0 +1,112 @@
local modules = require('lualine_require').lazy_require { notices = 'lualine.utils.notices' }
local function add_notice(notice)
modules.notices.add_notice('theme(base16): ' .. notice)
end
local function setup(colors)
local theme = {
normal = {
a = { fg = colors.bg, bg = colors.normal },
b = { fg = colors.light_fg, bg = colors.alt_bg },
c = { fg = colors.fg, bg = colors.bg },
},
replace = {
a = { fg = colors.bg, bg = colors.replace },
b = { fg = colors.light_fg, bg = colors.alt_bg },
},
insert = {
a = { fg = colors.bg, bg = colors.insert },
b = { fg = colors.light_fg, bg = colors.alt_bg },
},
visual = {
a = { fg = colors.bg, bg = colors.visual },
b = { fg = colors.light_fg, bg = colors.alt_bg },
},
inactive = {
a = { fg = colors.dark_fg, bg = colors.bg },
b = { fg = colors.dark_fg, bg = colors.bg },
c = { fg = colors.dark_fg, bg = colors.bg },
},
}
theme.command = theme.normal
theme.terminal = theme.insert
return theme
end
local function setup_default()
return setup {
bg = '#282a2e',
alt_bg = '#373b41',
dark_fg = '#969896',
fg = '#b4b7b4',
light_fg = '#c5c8c6',
normal = '#81a2be',
insert = '#b5bd68',
visual = '#b294bb',
replace = '#de935f',
}
end
local function setup_base16_nvim()
-- Continue to load nvim-base16
local loaded, base16 = pcall(require, 'base16-colorscheme')
if not loaded then
add_notice(
'nvim-base16 is not currently present in your runtimepath, make sure it is properly installed,'
.. ' fallback to default colors.'
)
return nil
end
if not base16.colors and not vim.env.BASE16_THEME then
add_notice(
'nvim-base16 is not loaded yet, you should update your configuration to load it before lualine'
.. ' so that the colors from your colorscheme can be used, fallback to "tomorrow-night" theme.'
)
elseif not base16.colors and not base16.colorschemes[vim.env.BASE16_THEME] then
add_notice(
'The colorscheme "%s" defined by the environment variable "BASE16_THEME" is not handled by'
.. ' nvim-base16, fallback to "tomorrow-night" theme.'
)
end
local colors = base16.colors or base16.colorschemes[vim.env.BASE16_THEME or 'tomorrow-night']
return setup {
bg = colors.base01,
alt_bg = colors.base02,
dark_fg = colors.base03,
fg = colors.base04,
light_fg = colors.base05,
normal = colors.base0D,
insert = colors.base0B,
visual = colors.base0E,
replace = colors.base09,
}
end
local function setup_base16_vim()
-- Check if tinted-theming/base16-vim is already loaded
if vim.g.base16_gui00 and vim.g.base16_gui0F then
return setup {
bg = vim.g.base16_gui01,
alt_bg = vim.g.base16_gui02,
dark_fg = vim.g.base16_gui03,
fg = vim.g.base16_gui04,
light_fg = vim.g.base16_gui05,
normal = vim.g.base16_gui0D,
insert = vim.g.base16_gui0B,
visual = vim.g.base16_gui0E,
replace = vim.g.base16_gui09,
}
end
return nil
end
return setup_base16_vim() or setup_base16_nvim() or setup_default()

View File

@ -0,0 +1,38 @@
-- Copyright (c) 2020-2021 Shatur95
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
gray = '#3C3C3C',
lightred = '#D16969',
blue = '#569CD6',
pink = '#C586C0',
black = '#262626',
white = '#D4D4D4',
green = '#608B4E',
}
return {
normal = {
b = { fg = colors.green, bg = colors.black },
a = { fg = colors.black, bg = colors.green, gui = 'bold' },
c = { fg = colors.white, bg = colors.black },
},
visual = {
b = { fg = colors.pink, bg = colors.black },
a = { fg = colors.black, bg = colors.pink, gui = 'bold' },
},
inactive = {
b = { fg = colors.black, bg = colors.blue },
a = { fg = colors.white, bg = colors.gray, gui = 'bold' },
},
replace = {
b = { fg = colors.lightred, bg = colors.black },
a = { fg = colors.black, bg = colors.lightred, gui = 'bold' },
c = { fg = colors.white, bg = colors.black },
},
insert = {
b = { fg = colors.blue, bg = colors.black },
a = { fg = colors.black, bg = colors.blue, gui = 'bold' },
c = { fg = colors.white, bg = colors.black },
},
}

View File

@ -0,0 +1,48 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit itchyny, jackno (lightline)
-- stylua: ignore
local colors = {
gray = '#44475a',
lightgray = '#5f6a8e',
orange = '#ffb86c',
purple = '#bd93f9',
red = '#ff5555',
yellow = '#f1fa8c',
green = '#50fa7b',
white = '#f8f8f2',
black = '#282a36',
}
return {
normal = {
a = { bg = colors.purple, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.gray, fg = colors.white },
},
insert = {
a = { bg = colors.green, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.gray, fg = colors.white },
},
visual = {
a = { bg = colors.yellow, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.gray, fg = colors.white },
},
replace = {
a = { bg = colors.red, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.gray, fg = colors.white },
},
command = {
a = { bg = colors.orange, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.gray, fg = colors.white },
},
inactive = {
a = { bg = colors.gray, fg = colors.white, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.gray, fg = colors.white },
},
}

View File

@ -0,0 +1,53 @@
-- Copyright (c) 2020-2021 gnuyent
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
bg0 = '#323d43',
bg1 = '#3c474d',
bg3 = '#505a60',
fg = '#d8caac',
aqua = '#87c095',
green = '#a7c080',
orange = '#e39b7b',
purple = '#d39bb6',
red = '#e68183',
grey1 = '#868d80',
}
return {
normal = {
a = { bg = colors.green, fg = colors.bg0, gui = 'bold' },
b = { bg = colors.bg3, fg = colors.fg },
c = { bg = colors.bg1, fg = colors.fg },
},
insert = {
a = { bg = colors.fg, fg = colors.bg0, gui = 'bold' },
b = { bg = colors.bg3, fg = colors.fg },
c = { bg = colors.bg1, fg = colors.fg },
},
visual = {
a = { bg = colors.red, fg = colors.bg0, gui = 'bold' },
b = { bg = colors.bg3, fg = colors.fg },
c = { bg = colors.bg1, fg = colors.fg },
},
replace = {
a = { bg = colors.orange, fg = colors.bg0, gui = 'bold' },
b = { bg = colors.bg3, fg = colors.fg },
c = { bg = colors.bg1, fg = colors.fg },
},
command = {
a = { bg = colors.aqua, fg = colors.bg0, gui = 'bold' },
b = { bg = colors.bg3, fg = colors.fg },
c = { bg = colors.bg1, fg = colors.fg },
},
terminal = {
a = { bg = colors.purple, fg = colors.bg0, gui = 'bold' },
b = { bg = colors.bg3, fg = colors.fg },
c = { bg = colors.bg1, fg = colors.fg },
},
inactive = {
a = { bg = colors.bg1, fg = colors.grey1, gui = 'bold' },
b = { bg = colors.bg1, fg = colors.grey1 },
c = { bg = colors.bg1, fg = colors.grey1 },
},
}

View File

@ -0,0 +1,29 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
fg1 = '#282828',
color2 = '#504945',
fg2 = '#ddc7a1',
color3 = '#32302f',
color4 = '#a89984',
color5 = '#7daea3',
color6 = '#a9b665',
color7 = '#d8a657',
color8 = '#d3869b',
color9 = '#ea6962',
}
return {
normal = {
a = { fg = colors.fg1, bg = colors.color4, gui = 'bold' },
b = { fg = colors.fg2, bg = colors.color2 },
c = { fg = colors.fg2, bg = colors.color3 },
},
command = { a = { fg = colors.fg1, bg = colors.color5, gui = 'bold' } },
inactive = { a = { fg = colors.fg2, bg = colors.color2 } },
insert = { a = { fg = colors.fg1, bg = colors.color6, gui = 'bold' } },
replace = { a = { fg = colors.fg1, bg = colors.color7, gui = 'bold' } },
terminal = { a = { fg = colors.fg1, bg = colors.color8, gui = 'bold' } },
visual = { a = { fg = colors.fg1, bg = colors.color9, gui = 'bold' } },
}

View File

@ -0,0 +1,7 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: itchyny(lightline)
-- License: MIT License
local background = vim.opt.background:get()
return require('lualine.themes.gruvbox_' .. background)

View File

@ -0,0 +1,48 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
black = '#282828',
white = '#ebdbb2',
red = '#fb4934',
green = '#b8bb26',
blue = '#83a598',
yellow = '#fe8019',
gray = '#a89984',
darkgray = '#3c3836',
lightgray = '#504945',
inactivegray = '#7c6f64',
}
return {
normal = {
a = { bg = colors.gray, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.darkgray, fg = colors.gray },
},
insert = {
a = { bg = colors.blue, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.lightgray, fg = colors.white },
},
visual = {
a = { bg = colors.yellow, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.inactivegray, fg = colors.black },
},
replace = {
a = { bg = colors.red, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.black, fg = colors.white },
},
command = {
a = { bg = colors.green, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.inactivegray, fg = colors.black },
},
inactive = {
a = { bg = colors.darkgray, fg = colors.gray, gui = 'bold' },
b = { bg = colors.darkgray, fg = colors.gray },
c = { bg = colors.darkgray, fg = colors.gray },
},
}

View File

@ -0,0 +1,47 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
black = '#3c3836',
white = '#f9f5d7',
orange = '#af3a03',
green = '#427b58',
blue = '#076678',
gray = '#d5c4a1',
darkgray = '#7c6f64',
lightgray = '#ebdbb2',
inactivegray = '#a89984'
}
return {
normal = {
a = { bg = colors.darkgray, fg = colors.white, gui = 'bold' },
b = { bg = colors.gray, fg = colors.darkgray },
c = { bg = colors.lightgray, fg = colors.darkgray },
},
insert = {
a = { bg = colors.blue, fg = colors.white, gui = 'bold' },
b = { bg = colors.gray, fg = colors.darkgray },
c = { bg = colors.gray, fg = colors.black },
},
visual = {
a = { bg = colors.orange, fg = colors.white, gui = 'bold' },
b = { bg = colors.gray, fg = colors.darkgray },
c = { bg = colors.darkgray, fg = colors.white },
},
replace = {
a = { bg = colors.green, fg = colors.white, gui = 'bold' },
b = { bg = colors.gray, fg = colors.darkgray },
c = { bg = colors.gray, fg = colors.black },
},
command = {
a = { bg = colors.darkgray, fg = colors.white, gui = 'bold' },
b = { bg = colors.gray, fg = colors.darkgray },
c = { bg = colors.lightgray, fg = colors.darkgray },
},
inactive = {
a = { bg = colors.lightgray, fg = colors.inactivegray },
b = { bg = colors.lightgray, fg = colors.inactivegray },
c = { bg = colors.lightgray, fg = colors.inactivegray },
},
}

View File

@ -0,0 +1,48 @@
-- Copyright (c) 2021 Jnhtr
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
black = '#1c1e26',
white = '#6C6F93',
red = '#F43E5C',
green = '#09F7A0',
blue = '#25B2BC',
yellow = '#F09383',
gray = '#E95678',
darkgray = '#1A1C23',
lightgray = '#2E303E',
inactivegray = '#1C1E26',
}
return {
normal = {
a = { bg = colors.gray, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.darkgray, fg = colors.white },
},
insert = {
a = { bg = colors.blue, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.darkgray, fg = colors.white },
},
visual = {
a = { bg = colors.yellow, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.darkgray, fg = colors.white },
},
replace = {
a = { bg = colors.red, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.darkgray, fg = colors.white },
},
command = {
a = { bg = colors.green, fg = colors.black, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.white },
c = { bg = colors.darkgray, fg = colors.white },
},
inactive = {
a = { bg = colors.inactivegray, fg = colors.lightgray, gui = 'bold' },
b = { bg = colors.inactivegray, fg = colors.lightgray },
c = { bg = colors.inactivegray, fg = colors.lightgray },
},
}

View File

@ -0,0 +1,7 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: itchyny(lightline)
-- License: MIT License
local background = vim.opt.background:get()
return require('lualine.themes.iceberg_' .. background)

View File

@ -0,0 +1,42 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Generated by lightline to lualine theme converter
-- https://gist.github.com/shadmansaleh/000871c9a608a012721c6acc6d7a19b9
-- stylua: ignore
local colors = {
color2 = '#161821',
color3 = '#b4be82',
color4 = '#c6c8d1',
color5 = '#2e313f',
color8 = '#e2a478',
color9 = '#3e445e',
color10 = '#0f1117',
color11 = '#17171b',
color12 = '#818596',
color15 = '#84a0c6',
}
return {
visual = {
a = { fg = colors.color2, bg = colors.color3, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
replace = {
a = { fg = colors.color2, bg = colors.color8, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
inactive = {
a = { fg = colors.color9, bg = colors.color10, gui = 'bold' },
b = { fg = colors.color9, bg = colors.color10 },
c = { fg = colors.color9, bg = colors.color10 },
},
normal = {
a = { fg = colors.color11, bg = colors.color12, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
c = { fg = colors.color4, bg = colors.color10 },
},
insert = {
a = { fg = colors.color2, bg = colors.color15, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
}

View File

@ -0,0 +1,40 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Generated by lightline to lualine theme converter
-- https://gist.github.com/shadmansaleh/000871c9a608a012721c6acc6d7a19b9
-- stylua: ignore
local colors = {
color5 = '#668e3d',
color8 = '#757ca3',
color9 = '#8b98b6',
color10 = '#cad0de',
color11 = '#2d539e',
color0 = '#e8e9ec',
color1 = '#9fa6c0',
color2 = '#c57339',
}
return {
replace = {
b = { fg = colors.color0, bg = colors.color1 },
a = { fg = colors.color0, bg = colors.color2, gui = 'bold' },
},
visual = {
b = { fg = colors.color0, bg = colors.color1 },
a = { fg = colors.color0, bg = colors.color5, gui = 'bold' },
},
normal = {
b = { fg = colors.color0, bg = colors.color1 },
a = { fg = colors.color0, bg = colors.color8, gui = 'bold' },
c = { fg = colors.color9, bg = colors.color10 },
},
inactive = {
b = { fg = colors.color9, bg = colors.color10 },
a = { fg = colors.color9, bg = colors.color10, gui = 'bold' },
c = { fg = colors.color9, bg = colors.color10 },
},
insert = {
b = { fg = colors.color0, bg = colors.color1 },
a = { fg = colors.color0, bg = colors.color11, gui = 'bold' },
},
}

View File

@ -0,0 +1,41 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Generated by lightline to lualine theme converter
-- https://gist.github.com/shadmansaleh/000871c9a608a012721c6acc6d7a19b9
-- stylua: ignore
local colors = {
color2 = '#30302c',
color3 = '#f0a0c0',
color4 = '#e8e8d3',
color5 = '#4e4e43',
color8 = '#cf6a4c',
color9 = '#666656',
color10 = '#808070',
color11 = '#8197bf',
color14 = '#99ad6a',
}
return {
visual = {
a = { fg = colors.color2, bg = colors.color3, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
replace = {
a = { fg = colors.color2, bg = colors.color8, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
inactive = {
c = { fg = colors.color9, bg = colors.color2 },
a = { fg = colors.color10, bg = colors.color2, gui = 'bold' },
b = { fg = colors.color9, bg = colors.color2 },
},
normal = {
c = { fg = colors.color10, bg = colors.color2 },
a = { fg = colors.color2, bg = colors.color11, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
insert = {
a = { fg = colors.color2, bg = colors.color14, gui = 'bold' },
b = { fg = colors.color4, bg = colors.color5 },
},
}

View File

@ -0,0 +1,42 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: Lokesh Krishna(lightline)
-- stylua: ignore
local colors = {
fg = '#eeffff',
bg = '#263238',
blue = '#82aaff',
green = '#c3e88d',
purple = '#c792ea',
red1 = '#f07178',
red2 = '#ff5370',
yellow = '#ffcb6b',
gray1 = '#314549',
gray2 = '#2E3C43',
gray3 = '#515559',
}
return {
normal = {
a = { fg = colors.bg, bg = colors.blue, gui = 'bold' },
b = { fg = colors.fg, bg = colors.gray3 },
c = { fg = colors.fg, bg = colors.gray2 },
},
insert = {
a = { fg = colors.bg, bg = colors.green, gui = 'bold' },
b = { fg = colors.fg, bg = colors.gray3 },
},
visual = {
a = { fg = colors.bg, bg = colors.purple, gui = 'bold' },
b = { fg = colors.fg, bg = colors.gray3 },
},
replace = {
a = { fg = colors.bg, bg = colors.red1, gui = 'bold' },
b = { fg = colors.fg, bg = colors.gray3 },
},
inactive = {
a = { fg = colors.fg, bg = colors.bg, gui = 'bold' },
b = { fg = colors.fg, bg = colors.bg },
c = { fg = colors.fg, bg = colors.gray2 },
},
}

View File

@ -0,0 +1,48 @@
-- Copyright (c) 2020-2021 ronniedroid
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
black = '#000000',
white = '#eeeeee',
red = '#ffa0a0',
green = '#88cf88',
blue = '#92baff',
magenta = '#feacd0',
cyan = '#a0bfdf',
gray = '#2f2f2f',
darkgray = '#202020',
lightgray = '#434343'
}
return {
normal = {
a = { bg = colors.blue, fg = colors.lightgray, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.blue },
c = { bg = colors.gray, fg = colors.white },
},
insert = {
a = { bg = colors.cyan, fg = colors.lightgray, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.cyan },
c = { bg = colors.gray, fg = colors.white },
},
visual = {
a = { bg = colors.magenta, fg = colors.lightgray, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.magenta },
c = { bg = colors.gray, fg = colors.white },
},
replace = {
a = { bg = colors.red, fg = colors.lightgray, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.red },
c = { bg = colors.gray, fg = colors.white },
},
command = {
a = { bg = colors.green, fg = colors.lightgray, gui = 'bold' },
b = { bg = colors.lightgray, fg = colors.green },
c = { bg = colors.gray, fg = colors.white },
},
inactive = {
a = { bg = colors.darkgray, fg = colors.lightgray, gui = 'bold' },
b = { bg = colors.darkgray, fg = colors.lightgray },
c = { bg = colors.darkgray, fg = colors.lightgray },
},
}

View File

@ -0,0 +1,31 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: challsted(lightline)
-- stylua: ignore
local colors = {
black = '#232526',
gray = '#808080',
white = '#f8f8f2',
cyan = '#66d9ef',
green = '#a6e22e',
orange = '#ef5939',
pink = '#f92672',
red = '#ff0000',
yellow = '#e6db74',
}
return {
normal = {
a = { fg = colors.black, bg = colors.cyan, gui = 'bold' },
b = { fg = colors.black, bg = colors.pink },
c = { fg = colors.orange, bg = colors.black },
},
insert = { a = { fg = colors.black, bg = colors.green, gui = 'bold' } },
visual = { a = { fg = colors.black, bg = colors.yellow, gui = 'bold' } },
replace = { a = { fg = colors.black, bg = colors.red, gui = 'bold' } },
inactive = {
a = { fg = colors.pink, bg = colors.black, gui = 'bold' },
b = { fg = colors.white, bg = colors.pink },
c = { fg = colors.gray, bg = colors.black },
},
}

View File

@ -0,0 +1,40 @@
-- moonfly color scheme for lualine
--
-- URL: github.com/bluz71/vim-moonfly-colors
-- License: MIT (https://opensource.org/licenses/MIT)
-- stylua: ignore
local colors = {
color3 = '#303030',
color6 = '#9e9e9e',
color7 = '#80a0ff',
color8 = '#ae81ff',
color0 = '#1c1c1c',
color1 = '#ff5189',
color2 = '#c6c6c6',
}
return {
replace = {
a = { fg = colors.color0, bg = colors.color1, gui = 'bold' },
b = { fg = colors.color2, bg = colors.color3 },
},
inactive = {
a = { fg = colors.color6, bg = colors.color3, gui = 'bold' },
b = { fg = colors.color6, bg = colors.color3 },
c = { fg = colors.color6, bg = colors.color3 },
},
normal = {
a = { fg = colors.color0, bg = colors.color7, gui = 'bold' },
b = { fg = colors.color2, bg = colors.color3 },
c = { fg = colors.color2, bg = colors.color3 },
},
visual = {
a = { fg = colors.color0, bg = colors.color8, gui = 'bold' },
b = { fg = colors.color2, bg = colors.color3 },
},
insert = {
a = { fg = colors.color0, bg = colors.color2, gui = 'bold' },
b = { fg = colors.color2, bg = colors.color3 },
},
}

View File

@ -0,0 +1,37 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
color3 = '#2c3043',
color6 = '#a1aab8',
color7 = '#82aaff',
color8 = '#ae81ff',
color0 = '#092236',
color1 = '#ff5874',
color2 = '#c3ccdc',
}
return {
replace = {
a = { fg = colors.color0, bg = colors.color1, gui = 'bold' },
b = { fg = colors.color2, bg = colors.color3 },
},
inactive = {
a = { fg = colors.color6, bg = colors.color3, gui = 'bold' },
b = { fg = colors.color6, bg = colors.color3 },
c = { fg = colors.color6, bg = colors.color3 },
},
normal = {
a = { fg = colors.color0, bg = colors.color7, gui = 'bold' },
b = { fg = colors.color2, bg = colors.color3 },
c = { fg = colors.color2, bg = colors.color3 },
},
visual = {
a = { fg = colors.color0, bg = colors.color8, gui = 'bold' },
b = { fg = colors.color2, bg = colors.color3 },
},
insert = {
a = { fg = colors.color0, bg = colors.color2, gui = 'bold' },
b = { fg = colors.color2, bg = colors.color3 },
},
}

View File

@ -0,0 +1,28 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
nord1 = '#3B4252',
nord3 = '#4C566A',
nord5 = '#E5E9F0',
nord6 = '#ECEFF4',
nord7 = '#8FBCBB',
nord8 = '#88C0D0',
nord13 = '#EBCB8B',
}
return {
normal = {
a = { fg = colors.nord1, bg = colors.nord8, gui = 'bold' },
b = { fg = colors.nord5, bg = colors.nord1 },
c = { fg = colors.nord5, bg = colors.nord3 },
},
insert = { a = { fg = colors.nord1, bg = colors.nord6, gui = 'bold' } },
visual = { a = { fg = colors.nord1, bg = colors.nord7, gui = 'bold' } },
replace = { a = { fg = colors.nord1, bg = colors.nord13, gui = 'bold' } },
inactive = {
a = { fg = colors.nord1, bg = colors.nord8, gui = 'bold' },
b = { fg = colors.nord5, bg = colors.nord1 },
c = { fg = colors.nord5, bg = colors.nord1 },
},
}

View File

@ -0,0 +1,36 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: Zoltan Dalmadi(lightline)
-- stylua: ignore
local colors = {
blue = '#61afef',
green = '#98c379',
purple = '#c678dd',
cyan = '#56b6c2',
red1 = '#e06c75',
red2 = '#be5046',
yellow = '#e5c07b',
fg = '#abb2bf',
bg = '#282c34',
gray1 = '#828997',
gray2 = '#2c323c',
gray3 = '#3e4452',
}
return {
normal = {
a = { fg = colors.bg, bg = colors.green, gui = 'bold' },
b = { fg = colors.fg, bg = colors.gray3 },
c = { fg = colors.fg, bg = colors.gray2 },
},
command = { a = { fg = colors.bg, bg = colors.yellow, gui = 'bold' } },
insert = { a = { fg = colors.bg, bg = colors.blue, gui = 'bold' } },
visual = { a = { fg = colors.bg, bg = colors.purple, gui = 'bold' } },
terminal = { a = { fg = colors.bg, bg = colors.cyan, gui = 'bold' } },
replace = { a = { fg = colors.bg, bg = colors.red1, gui = 'bold' } },
inactive = {
a = { fg = colors.gray1, bg = colors.bg, gui = 'bold' },
b = { fg = colors.gray1, bg = colors.bg },
c = { fg = colors.gray1, bg = colors.gray2 },
},
}

View File

@ -0,0 +1,34 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: Zoltan Dalmadi(lightline)
-- stylua: ignore
local colors = {
blue = '#4078f2',
green = '#50a14f',
purple = '#a626a4',
red1 = '#e45649',
red2 = '#ca1243',
yellow = '#c18401',
fg = '#494b53',
bg = '#fafafa',
gray1 = '#696c77',
gray2 = '#f0f0f0',
gray3 = '#d0d0d0',
}
return {
normal = {
a = { fg = colors.bg, bg = colors.green, gui = 'bold' },
b = { fg = colors.fg, bg = colors.gray3 },
c = { fg = colors.fg, bg = colors.gray2 },
},
command = { a = { fg = colors.bg, bg = colors.yellow, gui = 'bold' } },
insert = { a = { fg = colors.bg, bg = colors.blue, gui = 'bold' } },
visual = { a = { fg = colors.bg, bg = colors.purple, gui = 'bold' } },
replace = { a = { fg = colors.bg, bg = colors.red1, gui = 'bold' } },
inactive = {
a = { fg = colors.bg, bg = colors.gray3, gui = 'bold' },
b = { fg = colors.bg, bg = colors.gray3 },
c = { fg = colors.gray3, bg = colors.gray2 },
},
}

View File

@ -0,0 +1,47 @@
-- Copyright (c) 2020-2021 IGI-111
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
vertsplit = '#181A1F',
special_grey = '#3B4048',
menu_grey = '#3E4452',
cursor_grey = '#2C323C',
gutter_fg_grey = '#4B5263',
blue = '#82b1ff',
dark_red = '#BE5046',
white = '#bfc7d5',
green = '#C3E88D',
purple = '#c792ea',
yellow = '#ffcb6b',
light_red = '#ff869a',
red = '#ff5370',
dark_yellow = '#F78C6C',
cyan = '#89DDFF',
comment_grey = '#697098',
black = '#292D3E',
}
return {
normal = {
a = { fg = colors.black, bg = colors.purple, gui = 'bold' },
b = { fg = colors.purple, bg = colors.menu_grey },
c = { fg = colors.comment_grey, bg = colors.black },
},
insert = {
a = { fg = colors.black, bg = colors.blue, gui = 'bold' },
b = { fg = colors.blue, bg = colors.menu_grey },
},
visual = {
a = { fg = colors.black, bg = colors.cyan, gui = 'bold' },
b = { fg = colors.cyan, bg = colors.menu_grey },
},
replace = {
a = { fg = colors.black, bg = colors.green, gui = 'bold' },
b = { fg = colors.green, bg = colors.menu_grey },
},
inactive = {
a = { fg = colors.black, bg = colors.menu_grey, gui = 'bold' },
b = { fg = colors.black, bg = colors.menu_grey },
c = { fg = colors.black, bg = colors.menu_grey },
},
}

View File

@ -0,0 +1,42 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: TKNGUE(lightline)
-- stylua: ignore
local colors = {
red = '#df0000',
green = '#008700',
blue = '#00afaf',
pink = '#afdf00',
olive = '#dfaf5f',
navy = '#df875f',
orange = '#d75f00',
purple = '#8959a8',
aqua = '#3e999f',
foreground = '#d0d0d0',
background = '#444444',
window = '#efefef',
status = '#c6c6c6',
error = '#5f0000',
statusline_active_fg = '#1c1c1c',
statusline_active_bg = '#5f8787',
statusline_inactive_fg = '#c6c6c6',
statusline_inactive_bg = '#444444',
visual_fg = '#000000',
visual_bg = '#8787af',
}
return {
normal = {
a = { fg = colors.foreground, bg = colors.background, gui = 'bold' },
b = { fg = colors.statusline_active_fg, bg = colors.status },
c = { fg = colors.statusline_active_fg, bg = colors.statusline_active_bg },
},
insert = { a = { fg = colors.background, bg = colors.blue, gui = 'bold' } },
visual = { a = { fg = colors.visual_fg, bg = colors.visual_bg, gui = 'bold' } },
replace = { a = { fg = colors.background, bg = colors.pink, gui = 'bold' } },
inactive = {
a = { fg = colors.foreground, bg = colors.background, gui = 'bold' },
b = { fg = colors.foreground, bg = colors.background },
c = { fg = colors.foreground, bg = colors.background },
},
}

View File

@ -0,0 +1,40 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: TKNGUE(lightline)
-- stylua: ignore
local colors = {
red = '#df0000',
green = '#008700',
blue = '#4271ae',
pink = '#d7005f',
olive = '#718c00',
navy = '#005f87',
orange = '#d75f00',
purple = '#8959a8',
aqua = '#3e999f',
foreground = '#4d4d4c',
background = '#F5F5F5',
window = '#efefef',
status = '#3e999f',
error = '#ffafdf',
statusline_active_fg = '#efefef',
statusline_active_bg = '#005f87',
statusline_inactive_fg = '#4d4d4c',
statusline_inactive_bg = '#dadada',
}
return {
normal = {
a = { fg = colors.foreground, bg = colors.background, gui = 'bold' },
b = { fg = colors.statusline_active_fg, bg = colors.status },
c = { fg = colors.statusline_active_fg, bg = colors.statusline_active_bg },
},
insert = { a = { fg = colors.blue, bg = colors.background, gui = 'bold' } },
visual = { a = { fg = colors.background, bg = colors.orange, gui = 'bold' } },
replace = { a = { fg = colors.background, bg = colors.pink, gui = 'bold' } },
inactive = {
a = { fg = colors.foreground, bg = colors.background, gui = 'bold' },
b = { fg = colors.foreground, bg = colors.background },
c = { fg = colors.foreground, bg = colors.background },
},
}

View File

@ -0,0 +1,44 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local Colors = {
white = '#ffffff',
darkestgreen = '#005f00',
brightgreen = '#afdf00',
darkestcyan = '#005f5f',
mediumcyan = '#87dfff',
darkestblue = '#005f87',
darkred = '#870000',
brightred = '#df0000',
brightorange = '#ff8700',
gray1 = '#262626',
gray2 = '#303030',
gray4 = '#585858',
gray5 = '#606060',
gray7 = '#9e9e9e',
gray10 = '#f0f0f0',
}
local M = {
normal = {
a = { fg = Colors.darkestgreen, bg = Colors.brightgreen, gui = 'bold' },
b = { fg = Colors.gray10, bg = Colors.gray5 },
c = { fg = Colors.gray7, bg = Colors.gray2 },
},
insert = {
a = { fg = Colors.darkestcyan, bg = Colors.white, gui = 'bold' },
b = { fg = Colors.darkestcyan, bg = Colors.mediumcyan },
c = { fg = Colors.mediumcyan, bg = Colors.darkestblue },
},
visual = { a = { fg = Colors.darkred, bg = Colors.brightorange, gui = 'bold' } },
replace = { a = { fg = Colors.white, bg = Colors.brightred, gui = 'bold' } },
inactive = {
a = { fg = Colors.gray1, bg = Colors.gray5, gui = 'bold' },
b = { fg = Colors.gray1, bg = Colors.gray5 },
c = { bg = Colors.gray1, fg = Colors.gray5 },
},
}
M.terminal = M.insert
return M

View File

@ -0,0 +1,60 @@
-- Copyright (c) 2021 Ashish Panigrahi
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
black = '#202020',
neon = '#DFFF00',
white = '#FFFFFF',
green = '#00D700',
purple = '#5F005F',
blue = '#00DFFF',
darkblue = '#00005F',
navyblue = '#000080',
brightgreen = '#9CFFD3',
gray = '#444444',
darkgray = '#3c3836',
lightgray = '#504945',
inactivegray = '#7c6f64',
orange = '#FFAF00',
red = '#5F0000',
brightorange = '#C08A20',
brightred = '#AF0000',
cyan = '#00DFFF',
}
local M = {
normal = {
a = { bg = colors.neon, fg = colors.black, gui = 'bold' },
b = { bg = colors.gray, fg = colors.white },
c = { bg = colors.black, fg = colors.brightgreen },
},
insert = {
a = { bg = colors.blue, fg = colors.darkblue, gui = 'bold' },
b = { bg = colors.navyblue, fg = colors.white },
c = { bg = colors.purple, fg = colors.white },
},
visual = {
a = { bg = colors.orange, fg = colors.black, gui = 'bold' },
b = { bg = colors.darkgray, fg = colors.white },
c = { bg = colors.red, fg = colors.white },
},
replace = {
a = { bg = colors.brightred, fg = colors.white, gui = 'bold' },
b = { bg = colors.cyan, fg = colors.darkblue },
c = { bg = colors.navyblue, fg = colors.white },
},
command = {
a = { bg = colors.green, fg = colors.black, gui = 'bold' },
b = { bg = colors.darkgray, fg = colors.white },
c = { bg = colors.black, fg = colors.brightgreen },
},
inactive = {
a = { bg = colors.darkgray, fg = colors.gray, gui = 'bold' },
b = { bg = colors.darkgray, fg = colors.gray },
c = { bg = colors.darkgray, fg = colors.gray },
},
}
M.terminal = M.insert
return M

View File

@ -0,0 +1,50 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local lualine_require = require('lualine_require')
local modules = lualine_require.lazy_require {
utils_notices = 'lualine.utils.notices',
}
local sep = package.config:sub(1, 1)
local wal_colors_path = table.concat({ os.getenv('HOME'), '.cache', 'wal', 'colors.sh' }, sep)
local wal_colors_file = io.open(wal_colors_path, 'r')
if wal_colors_file == nil then
modules.utils_notices.add_notice('lualine.nvim: ' .. wal_colors_path .. ' not found')
error('')
end
local ok, wal_colors_text = pcall(wal_colors_file.read, wal_colors_file, '*a')
wal_colors_file:close()
if not ok then
modules.utils_notices.add_notice('lualine.nvim: ' .. wal_colors_path .. ' could not be read: ' .. wal_colors_text)
error('')
end
local colors = {}
for line in vim.gsplit(wal_colors_text, '\n') do
if line:match("^[a-z0-9]+='#[a-fA-F0-9]+'$") ~= nil then
local i = line:find('=')
local key = line:sub(0, i - 1)
local value = line:sub(i + 2, #line - 1)
colors[key] = value
end
end
return {
normal = {
a = { fg = colors.background, bg = colors.color4, gui = 'bold' },
b = { fg = colors.foreground, bg = colors.color8 },
c = { fg = colors.foreground, bg = colors.background },
},
insert = { a = { fg = colors.background, bg = colors.color2, gui = 'bold' } },
visual = { a = { fg = colors.background, bg = colors.color3, gui = 'bold' } },
replace = { a = { fg = colors.background, bg = colors.color1, gui = 'bold' } },
inactive = {
a = { fg = colors.foreground, bg = colors.background, gui = 'bold' },
b = { fg = colors.foreground, bg = colors.background },
c = { fg = colors.foreground, bg = colors.background },
},
}

View File

@ -0,0 +1,41 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Generated by lightline to lualine theme converter
-- https://gist.github.com/shadmansaleh/000871c9a608a012721c6acc6d7a19b9
-- stylua: ignore
local colors = {
color5 = '#d7afaf',
color6 = '#666656',
color7 = '#808070',
color10 = '#87af87',
color13 = '#df5f87',
color14 = '#87afaf',
color0 = '#e8e8d3',
color1 = '#4e4e43',
color4 = '#30302c',
}
return {
visual = {
b = { fg = colors.color0, bg = colors.color1 },
a = { fg = colors.color4, bg = colors.color5, gui = 'bold' },
},
inactive = {
b = { fg = colors.color6, bg = colors.color4 },
c = { fg = colors.color6, bg = colors.color4 },
a = { fg = colors.color7, bg = colors.color4, gui = 'bold' },
},
insert = {
b = { fg = colors.color0, bg = colors.color1 },
a = { fg = colors.color4, bg = colors.color10, gui = 'bold' },
},
replace = {
b = { fg = colors.color0, bg = colors.color1 },
a = { fg = colors.color4, bg = colors.color13, gui = 'bold' },
},
normal = {
b = { fg = colors.color0, bg = colors.color1 },
c = { fg = colors.color7, bg = colors.color4 },
a = { fg = colors.color4, bg = colors.color14, gui = 'bold' },
},
}

View File

@ -0,0 +1,7 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: itchyny(lightline)
-- License: MIT License
local background = vim.opt.background:get()
return require('lualine.themes.solarized_' .. background)

View File

@ -0,0 +1,38 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: itchyny(lightline)
-- stylua: ignore
local colors = {
base03 = '#002b36',
base02 = '#073642',
base01 = '#586e75',
base00 = '#657b83',
base0 = '#839496',
base1 = '#93a1a1',
base2 = '#eee8d5',
base3 = '#fdf6e3',
yellow = '#b58900',
orange = '#cb4b16',
red = '#dc322f',
magenta = '#d33682',
violet = '#6c71c4',
blue = '#268bd2',
cyan = '#2aa198',
green = '#859900',
}
return {
normal = {
a = { fg = colors.base03, bg = colors.blue, gui = 'bold' },
b = { fg = colors.base03, bg = colors.base1 },
c = { fg = colors.base1, bg = colors.base02 },
},
insert = { a = { fg = colors.base03, bg = colors.green, gui = 'bold' } },
visual = { a = { fg = colors.base03, bg = colors.magenta, gui = 'bold' } },
replace = { a = { fg = colors.base03, bg = colors.red, gui = 'bold' } },
inactive = {
a = { fg = colors.base0, bg = colors.base02, gui = 'bold' },
b = { fg = colors.base03, bg = colors.base00 },
c = { fg = colors.base01, bg = colors.base02 },
},
}

View File

@ -0,0 +1,38 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: itchyny(lightline)
-- stylua: ignore
local colors = {
base3 = '#002b36',
base2 = '#073642',
base1 = '#586e75',
base0 = '#657b83',
base00 = '#839496',
base01 = '#93a1a1',
base02 = '#eee8d5',
base03 = '#fdf6e3',
yellow = '#b58900',
orange = '#cb4b16',
red = '#dc322f',
magenta = '#d33682',
violet = '#6c71c4',
blue = '#268bd2',
cyan = '#2aa198',
green = '#859900',
}
return {
normal = {
a = { fg = colors.base03, bg = colors.blue, gui = 'bold' },
b = { fg = colors.base03, bg = colors.base1 },
c = { fg = colors.base1, bg = colors.base02 },
},
insert = { a = { fg = colors.base03, bg = colors.green, gui = 'bold' } },
visual = { a = { fg = colors.base03, bg = colors.magenta, gui = 'bold' } },
replace = { a = { fg = colors.base03, bg = colors.red, gui = 'bold' } },
inactive = {
a = { fg = colors.base0, bg = colors.base02, gui = 'bold' },
b = { fg = colors.base03, bg = colors.base00 },
c = { fg = colors.base01, bg = colors.base02 },
},
}

View File

@ -0,0 +1,38 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- Credit: itchyny(lightline)
-- stylua: ignore
local colors = {
base03 = '#242424',
base023 = '#353535',
base02 = '#444444',
base01 = '#585858',
base00 = '#666666',
base0 = '#808080',
base1 = '#969696',
base2 = '#a8a8a8',
base3 = '#d0d0d0',
yellow = '#cae682',
orange = '#e5786d',
red = '#e5786d',
magenta = '#f2c68a',
blue = '#8ac6f2',
cyan = '#8ac6f2',
green = '#95e454',
}
return {
normal = {
a = { fg = colors.base02, bg = colors.blue, gui = 'bold' },
b = { fg = colors.base02, bg = colors.base0 },
c = { fg = colors.base2, bg = colors.base02 },
},
insert = { a = { fg = colors.base02, bg = colors.green, gui = 'bold' } },
visual = { a = { fg = colors.base02, bg = colors.magenta, gui = 'bold' } },
replace = { a = { fg = colors.base023, bg = colors.red, gui = 'bold' } },
inactive = {
a = { fg = colors.base1, bg = colors.base02, gui = 'bold' },
b = { fg = colors.base023, bg = colors.base01 },
c = { fg = colors.base1, bg = colors.base023 },
},
}

View File

@ -0,0 +1,43 @@
-- Adapted from https://github.com/rxi/classic/blob/master/classic.lua
local Object = {}
Object.__index = Object
-- luacheck: push no unused args
---Initializer
function Object:init(...) end
-- luacheck: pop
---Extend base class to create a child class
function Object:extend()
local cls = {}
for k, v in pairs(self) do
if k:find('__') == 1 then
cls[k] = v
end
end
cls.__index = cls
cls.super = self
setmetatable(cls, self)
return cls
end
-- luacheck: push no unused args
function Object:__tostring()
return 'Object'
end
-- luacheck: pop
---Creates a new object
function Object:new(...)
local obj = setmetatable({}, self)
obj:init(...)
return obj
end
---Creates a new object
function Object:__call(...)
return self:new(...)
end
return Object

View File

@ -0,0 +1,331 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local M = {}
-- stylua: ignore start
-- color conversion
local color_table = {
-- lookup table for cterm colors
-- format {'color_code', {r,g,b}}
-- Primary 3-bit (8 colors). Unique representation!
{'00', { 0, 0, 0 }},
{'01', { 128, 0, 0 }},
{'02', { 0, 128, 0 }},
{'03', { 128, 128, 0 }},
{'04', { 0, 0, 128 }},
{'05', { 128, 0, 128 }},
{'06', { 0, 128, 128 }},
{'07', { 192, 192, 192 }},
-- equivalent "bright" versions of original 8 colors.
{'08', { 128, 128, 128 }},
{'09', { 255, 0, 0 }},
{'10', { 0, 255, 0 }},
{'11', { 255, 255, 0 }},
{'12', { 0, 0, 255 }},
{'13', { 255, 0, 255 }},
{'14', { 0, 255, 255 }},
{'15', { 255, 255, 255 }},
-- Strictly ascending.
{'16', { 0, 0, 0 }},
{'17', { 0, 0, 95 }},
{'18', { 0, 0, 135 }},
{'19', { 0, 0, 175 }},
{'20', { 0, 0, 215 }},
{'21', { 0, 0, 255 }},
{'22', { 0, 95, 0 }},
{'23', { 0, 95, 95 }},
{'24', { 0, 95, 135 }},
{'25', { 0, 95, 175 }},
{'26', { 0, 95, 215 }},
{'27', { 0, 95, 255 }},
{'28', { 0, 135, 0 }},
{'29', { 0, 135, 95 }},
{'30', { 0, 135, 135 }},
{'31', { 0, 135, 175 }},
{'32', { 0, 135, 215 }},
{'33', { 0, 135, 255 }},
{'34', { 0, 175, 0 }},
{'35', { 0, 175, 95 }},
{'36', { 0, 175, 135 }},
{'37', { 0, 175, 175 }},
{'38', { 0, 175, 215 }},
{'39', { 0, 175, 255 }},
{'40', { 0, 215, 0 }},
{'41', { 0, 215, 95 }},
{'42', { 0, 215, 135 }},
{'43', { 0, 215, 175 }},
{'44', { 0, 215, 215 }},
{'45', { 0, 215, 255 }},
{'46', { 0, 255, 0 }},
{'47', { 0, 255, 95 }},
{'48', { 0, 255, 135 }},
{'49', { 0, 255, 175 }},
{'50', { 0, 255, 215 }},
{'51', { 0, 255, 255 }},
{'52', { 95, 0, 0 }},
{'53', { 95, 0, 95 }},
{'54', { 95, 0, 135 }},
{'55', { 95, 0, 175 }},
{'56', { 95, 0, 215 }},
{'57', { 95, 0, 255 }},
{'58', { 95, 95, 0 }},
{'59', { 95, 95, 95 }},
{'60', { 95, 95, 135 }},
{'61', { 95, 95, 175 }},
{'62', { 95, 95, 215 }},
{'63', { 95, 95, 255 }},
{'64', { 95, 135, 0 }},
{'65', { 95, 135, 95 }},
{'66', { 95, 135, 135 }},
{'67', { 95, 135, 175 }},
{'68', { 95, 135, 215 }},
{'69', { 95, 135, 255 }},
{'70', { 95, 175, 0 }},
{'71', { 95, 175, 95 }},
{'72', { 95, 175, 135 }},
{'73', { 95, 175, 175 }},
{'74', { 95, 175, 215 }},
{'75', { 95, 175, 255 }},
{'76', { 95, 215, 0 }},
{'77', { 95, 215, 95 }},
{'78', { 95, 215, 135 }},
{'79', { 95, 215, 175 }},
{'80', { 95, 215, 215 }},
{'81', { 95, 215, 255 }},
{'82', { 95, 255, 0 }},
{'83', { 95, 255, 95 }},
{'84', { 95, 255, 135 }},
{'85', { 95, 255, 175 }},
{'86', { 95, 255, 215 }},
{'87', { 95, 255, 255 }},
{'88', { 135, 0, 0 }},
{'89', { 135, 0, 95 }},
{'90', { 135, 0, 135 }},
{'91', { 135, 0, 175 }},
{'92', { 135, 0, 215 }},
{'93', { 135, 0, 255 }},
{'94', { 135, 95, 0 }},
{'95', { 135, 95, 95 }},
{'96', { 135, 95, 135 }},
{'97', { 135, 95, 175 }},
{'98', { 135, 95, 215 }},
{'99', { 135, 95, 255 }},
{'100', { 135, 135, 0 }},
{'101', { 135, 135, 95 }},
{'102', { 135, 135, 135 }},
{'103', { 135, 135, 175 }},
{'104', { 135, 135, 215 }},
{'105', { 135, 135, 255 }},
{'106', { 135, 175, 0 }},
{'107', { 135, 175, 95 }},
{'108', { 135, 175, 135 }},
{'109', { 135, 175, 175 }},
{'110', { 135, 175, 215 }},
{'111', { 135, 175, 255 }},
{'112', { 135, 215, 0 }},
{'113', { 135, 215, 95 }},
{'114', { 135, 215, 135 }},
{'115', { 135, 215, 175 }},
{'116', { 135, 215, 215 }},
{'117', { 135, 215, 255 }},
{'118', { 135, 255, 0 }},
{'119', { 135, 255, 95 }},
{'120', { 135, 255, 135 }},
{'121', { 135, 255, 175 }},
{'122', { 135, 255, 215 }},
{'123', { 135, 255, 255 }},
{'124', { 175, 0, 0 }},
{'125', { 175, 0, 95 }},
{'126', { 175, 0, 135 }},
{'127', { 175, 0, 175 }},
{'128', { 175, 0, 215 }},
{'129', { 175, 0, 255 }},
{'130', { 175, 95, 0 }},
{'131', { 175, 95, 95 }},
{'132', { 175, 95, 135 }},
{'133', { 175, 95, 175 }},
{'134', { 175, 95, 215 }},
{'135', { 175, 95, 255 }},
{'136', { 175, 135, 0 }},
{'137', { 175, 135, 95 }},
{'138', { 175, 135, 135 }},
{'139', { 175, 135, 175 }},
{'140', { 175, 135, 215 }},
{'141', { 175, 135, 255 }},
{'142', { 175, 175, 0 }},
{'143', { 175, 175, 95 }},
{'144', { 175, 175, 135 }},
{'145', { 175, 175, 175 }},
{'146', { 175, 175, 215 }},
{'147', { 175, 175, 255 }},
{'148', { 175, 215, 0 }},
{'149', { 175, 215, 95 }},
{'150', { 175, 215, 135 }},
{'151', { 175, 215, 175 }},
{'152', { 175, 215, 215 }},
{'153', { 175, 215, 255 }},
{'154', { 175, 255, 0 }},
{'155', { 175, 255, 95 }},
{'156', { 175, 255, 135 }},
{'157', { 175, 255, 175 }},
{'158', { 175, 255, 215 }},
{'159', { 175, 255, 255 }},
{'160', { 215, 0, 0 }},
{'161', { 215, 0, 95 }},
{'162', { 215, 0, 135 }},
{'163', { 215, 0, 175 }},
{'164', { 215, 0, 215 }},
{'165', { 215, 0, 255 }},
{'166', { 215, 95, 0 }},
{'167', { 215, 95, 95 }},
{'168', { 215, 95, 135 }},
{'169', { 215, 95, 175 }},
{'170', { 215, 95, 215 }},
{'171', { 215, 95, 255 }},
{'172', { 215, 135, 0 }},
{'173', { 215, 135, 95 }},
{'174', { 215, 135, 135 }},
{'175', { 215, 135, 175 }},
{'176', { 215, 135, 215 }},
{'177', { 215, 135, 255 }},
{'178', { 215, 175, 0 }},
{'179', { 215, 175, 95 }},
{'180', { 215, 175, 135 }},
{'181', { 215, 175, 175 }},
{'182', { 215, 175, 215 }},
{'183', { 215, 175, 255 }},
{'184', { 215, 215, 0 }},
{'185', { 215, 215, 95 }},
{'186', { 215, 215, 135 }},
{'187', { 215, 215, 175 }},
{'188', { 215, 215, 215 }},
{'189', { 215, 215, 255 }},
{'190', { 215, 255, 0 }},
{'191', { 215, 255, 95 }},
{'192', { 215, 255, 135 }},
{'193', { 215, 255, 175 }},
{'194', { 215, 255, 215 }},
{'195', { 215, 255, 255 }},
{'196', { 255, 0, 0 }},
{'197', { 255, 0, 95 }},
{'198', { 255, 0, 135 }},
{'199', { 255, 0, 175 }},
{'200', { 255, 0, 215 }},
{'201', { 255, 0, 255 }},
{'202', { 255, 95, 0 }},
{'203', { 255, 95, 95 }},
{'204', { 255, 95, 135 }},
{'205', { 255, 95, 175 }},
{'206', { 255, 95, 215 }},
{'207', { 255, 95, 255 }},
{'208', { 255, 135, 0 }},
{'209', { 255, 135, 95 }},
{'210', { 255, 135, 135 }},
{'211', { 255, 135, 175 }},
{'212', { 255, 135, 215 }},
{'213', { 255, 135, 255 }},
{'214', { 255, 175, 0 }},
{'215', { 255, 175, 95 }},
{'216', { 255, 175, 135 }},
{'217', { 255, 175, 175 }},
{'218', { 255, 175, 215 }},
{'219', { 255, 175, 255 }},
{'220', { 255, 215, 0 }},
{'221', { 255, 215, 95 }},
{'222', { 255, 215, 135 }},
{'223', { 255, 215, 175 }},
{'224', { 255, 215, 215 }},
{'225', { 255, 215, 255 }},
{'226', { 255, 255, 0 }},
{'227', { 255, 255, 95 }},
{'228', { 255, 255, 135 }},
{'229', { 255, 255, 175 }},
{'230', { 255, 255, 215 }},
{'231', { 255, 255, 255 }},
-- Gray-scale range.
{'232', { 8, 8, 8 }},
{'233', { 18, 18, 18 }},
{'234', { 28, 28, 28 }},
{'235', { 38, 38, 38 }},
{'236', { 48, 48, 48 }},
{'237', { 58, 58, 58 }},
{'238', { 68, 68, 68 }},
{'239', { 78, 78, 78 }},
{'240', { 88, 88, 88 }},
{'241', { 98, 98, 98 }},
{'242', { 108, 108, 108 }},
{'243', { 118, 118, 118 }},
{'244', { 128, 128, 128 }},
{'245', { 138, 138, 138 }},
{'246', { 148, 148, 148 }},
{'247', { 158, 158, 158 }},
{'248', { 168, 168, 168 }},
{'249', { 178, 178, 178 }},
{'250', { 188, 188, 188 }},
{'251', { 198, 198, 198 }},
{'252', { 208, 208, 208 }},
{'253', { 218, 218, 218 }},
{'254', { 228, 228, 228 }},
{'255', { 238, 238, 238 }},
}
-- stylua: ignore end
---converts #rrggbb formatted color to cterm ('0'-'255') color
---@param hex_color string
---@return string
function M.rgb2cterm(hex_color)
if hex_color == 'None' then
return 'None'
end
local function get_color_distance(color1, color2)
-- returns how much color2 deviates from color1
local dr = math.abs(color1[1] - color2[1]) / (color1[1] + 1) * 100
local dg = math.abs(color1[2] - color2[2]) / (color1[2] + 1) * 100
local db = math.abs(color1[3] - color2[3]) / (color1[3] + 1) * 100
return (dr + dg + db)
end
local r = tonumber(hex_color:sub(2, 3), 16)
local g = tonumber(hex_color:sub(4, 5), 16)
local b = tonumber(hex_color:sub(6, 7), 16)
-- check which cterm color is closest to hex colors in terms of rgb values
local closest_cterm_color = 0
local min_distance = 10000
for _, color in ipairs(color_table) do
local current_distance = get_color_distance(color[2], { r, g, b })
if current_distance < min_distance then
min_distance = current_distance
closest_cterm_color = color[1]
end
end
return closest_cterm_color
end
---converts color name (only ones supported by neovim) formatted colors to #rrggbb
---@param name string like red,green,grey
---@return string
function M.color_name2rgb(name)
local color_val = vim.api.nvim_get_color_by_name(name)
if color_val == -1 then
return '#' .. name -- Assuming it's 'rrggbb' without # not rad instead of red
end
return string.format('#%06x', color_val)
end
---converts cterm(0-255) to #rrggbb
---@param color number
---@return string
function M.cterm2rgb(color)
local color_data = color_table[color + 1]
if color_data ~= nil then
color_data = color_data[2]
return string.format('#%02x%02x%02x', color_data[1], color_data[2], color_data[3])
end
end
return M

View File

@ -0,0 +1,38 @@
local M = {}
local fns = {}
---Store fn with id in fns so it can be later called
---@param id integer component id (for now we are only doing one fn per component)
---@param fn function the actual function to store.
---@return number same id that was provided.
function M.register_fn(id, fn)
vim.validate {
id = { id, 'n' },
fn = { fn, 'f' },
}
fns[id] = fn
return id
end
---Get the function with id
---@param id number id of the fn to retrieve
---@return function
function M.get_fn(id)
vim.validate { id = { id, 'n' } }
return fns[id] or function() end
end
---Call the function of id with args
---@param id number
---@param ... any
---@return any
function M.call_fn(id, ...)
return M.get_fn(id)(...)
end
---Clear the fns table
function M.clear_fns()
fns = {}
end
return M

View File

@ -0,0 +1,54 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
--- wrapper around job api
--- creates a job handler when called
local Job = setmetatable({
--- start the job
start = function(self)
self.job_id = vim.fn.jobstart(self.args.cmd, self.args)
return self.job_id > 0
end,
--- stop the job. Also immediately disables io from the job.
stop = function(self)
if self.killed then
return
end
if self.job_id and self.job_id > 0 then
vim.fn.jobstop(self.job_id)
end
self.job_id = 0
self.killed = true
end,
-- Wraps callbacks so they are only called when job is alive
-- This avoids race conditions
wrap_cb_alive = function(self, name)
local original_cb = self.args[name]
if original_cb then
self.args[name] = function(...)
if not self.killed then
return original_cb(...)
end
end
end
end,
}, {
---create new job handler
---@param self table base job table
---@param args table same args as jobstart except cmd is also passed in part of it
---@return table new job handler
__call = function(self, args)
args = vim.deepcopy(args or {})
if type(args.cmd) == 'string' then
args.cmd = vim.split(args.cmd, ' ')
end
self.__index = self
local job = setmetatable({ args = args }, self)
job:wrap_cb_alive('on_stdout')
job:wrap_cb_alive('on_stderr')
job:wrap_cb_alive('on_stdin')
return job
end,
})
return Job

View File

@ -0,0 +1,257 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local lualine_require = require('lualine_require')
local require = lualine_require.require
local modules = lualine_require.lazy_require {
utils = 'lualine.utils.utils',
notice = 'lualine.utils.notices',
fn_store = 'lualine.utils.fn_store',
}
local is_valid_filename = lualine_require.is_valid_filename
local sep = lualine_require.sep
--- function that loads specific type of component
local component_types = {
-- loads custom component
custom = function(component)
return component[1](component)
end,
--- loads lua functions as component
lua_fun = function(component)
return require('lualine.components.special.function_component')(component)
end,
--- loads lua modules as components (ones in /lua/lualine/components/)
mod = function(component)
local ok, loaded_component = pcall(require, 'lualine.components.' .. component[1])
if ok then
component.component_name = component[1]
if type(loaded_component) == 'table' then
loaded_component = loaded_component(component)
elseif type(loaded_component) == 'function' then
component[1] = loaded_component
loaded_component = require('lualine.components.special.function_component')(component)
end
return loaded_component
end
end,
--- loads builtin statusline patterns as component
stl = function(component)
local stl_expr = component[1] -- Vim's %p %l statusline elements
component[1] = function()
return stl_expr
end
return require('lualine.components.special.function_component')(component)
end,
--- loads variables & options (g:,go:,b:,bo:...) as components
var = function(component)
return require('lualine.components.special.vim_var_component')(component)
end,
--- loads vim functions and lua expressions as components
['_'] = function(component)
return require('lualine.components.special.eval_func_component')(component)
end,
}
---load a component from component config
---@param component table component + component options
---@return table the loaded & initialized component
local function component_loader(component)
if type(component[1]) == 'function' then
return component_types.lua_fun(component)
elseif type(component[1]) == 'string' then
-- load the component
if component.type ~= nil then
if component_types[component.type] and component.type ~= 'lua_fun' then
return component_types[component.type](component)
elseif component.type == 'vim_fun' or component.type == 'lua_expr' then
return component_types['_'](component)
else
modules.notice.add_notice(string.format(
[[
### component.type
component type '%s' isn't recognised. Check if spelling is correct.]],
component.type
))
end
end
local loaded_component = component_types.mod(component)
if loaded_component then
return loaded_component
elseif string.char(component[1]:byte(1)) == '%' then
return component_types.stl(component)
elseif component[1]:find('[gvtwb]?o?:') == 1 then
return component_types.var(component)
else
return component_types['_'](component)
end
elseif type(component[1]) == 'table' then
return component_types.custom(component)
end
end
--- Shows notice about invalid types passed as component
--- @param index number the index of component in section table
--- @param component table containing component elements
--- return bool whether check passed or not
local function is_valid_component_type(index, component)
if type(component_types) == 'table' and type(index) == 'number' then
return true
end
modules.notice.add_notice(string.format(
[[
### Unrecognized component
Only functions, strings and tables can be used as component.
You seem to have a `%s` as component indexed as `%s`.
Something like:
```lua
%s = %s,
```
This commonly occurs when you forget to pass table with option for component.
When a component has option that component needs to be a table which holds
the component as first element and the options as key value pairs.
For example:
```lua
lualine_c = {
{'diagnostics',
sources = {'nvim'},
}
}
```
Notice the inner extra {} surrounding the component and it's options.
Make sure your config follows this.
]],
type(component),
index,
index,
vim.inspect(component)
))
return false
end
---loads all the section from a config
---@param sections table list of sections
---@param options table global options table
local function load_sections(sections, options)
for section_name, section in pairs(sections) do
for index, component in pairs(section) do
if (type(component) == 'string' or type(component) == 'function') or modules.utils.is_component(component) then
component = { component }
end
if is_valid_component_type(index, component) then
component.self = {}
component.self.section = section_name:match('lualine_(.*)')
-- apply default args
component = vim.tbl_extend('keep', component, options)
section[index] = component_loader(component)
end
end
end
end
---loads all the configs (active, inactive, tabline)
---@param config table user config
local function load_components(config)
local sec_names = { 'sections', 'inactive_sections', 'tabline', 'winbar', 'inactive_winbar' }
for _, section in ipairs(sec_names) do
load_sections(config[section], config.options)
end
end
---loads all the extensions
---@param config table user config
local function load_extensions(config)
local loaded_extensions = {}
local sec_names = { 'sections', 'inactive_sections', 'winbar', 'inactive_winbar' }
for _, extension in pairs(config.extensions) do
if type(extension) == 'string' then
local ok
ok, extension = pcall(require, 'lualine.extensions.' .. extension)
if not ok then
modules.notice.add_notice(string.format(
[[
### Extensions
Extension named `%s` was not found . Check if spelling is correct.
]],
extension
))
end
end
if type(extension) == 'table' then
local local_extension = modules.utils.deepcopy(extension)
for _, section in ipairs(sec_names) do
if local_extension[section] then
load_sections(local_extension[section], config.options)
end
end
if type(local_extension.init) == 'function' then
local_extension.init()
end
table.insert(loaded_extensions, local_extension)
end
end
config.extensions = loaded_extensions
end
---loads sections and extensions or entire user config
---@param config table user config
local function load_all(config)
require('lualine.component')._reset_components()
modules.fn_store.clear_fns()
require('lualine.utils.nvim_opts').reset_cache()
load_components(config)
load_extensions(config)
end
---loads a theme from lua module
---prioritizes external themes (from user config or other plugins) over the bundled ones
---@param theme_name string
---@return table theme definition from module
local function load_theme(theme_name)
assert(is_valid_filename(theme_name), 'Invalid filename')
local retval
local path = table.concat { 'lua/lualine/themes/', theme_name, '.lua' }
local files = vim.api.nvim_get_runtime_file(path, true)
if #files <= 0 then
path = table.concat { 'lua/lualine/themes/', theme_name, '/init.lua' }
files = vim.api.nvim_get_runtime_file(path, true)
end
local n_files = #files
if n_files == 0 then
-- No match found
error(path .. ' Not found')
elseif n_files == 1 then
-- when only one is found run that and return it's return value
retval = dofile(files[1])
else
-- put entries from user config path in front
local user_config_path = vim.fn.stdpath('config')
table.sort(files, function(a, b)
local pattern = table.concat { user_config_path, sep }
return string.match(a, pattern) or not string.match(b, pattern)
end)
-- More then 1 found . Use the first one that isn't in lualines repo
local lualine_repo_pattern = table.concat({ 'lualine.nvim', 'lua', 'lualine' }, sep)
local file_found = false
for _, file in ipairs(files) do
if not file:find(lualine_repo_pattern) then
retval = dofile(file)
file_found = true
break
end
end
if not file_found then
-- This shouldn't happen but somehow we have multiple files but they
-- appear to be in lualines repo . Just run the first one
retval = dofile(files[1])
end
end
return retval
end
return {
load_all = load_all,
load_theme = load_theme,
}

View File

@ -0,0 +1,54 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local Mode = {}
-- stylua: ignore
Mode.map = {
['n'] = 'NORMAL',
['no'] = 'O-PENDING',
['nov'] = 'O-PENDING',
['noV'] = 'O-PENDING',
['no\22'] = 'O-PENDING',
['niI'] = 'NORMAL',
['niR'] = 'NORMAL',
['niV'] = 'NORMAL',
['nt'] = 'NORMAL',
['ntT'] = 'NORMAL',
['v'] = 'VISUAL',
['vs'] = 'VISUAL',
['V'] = 'V-LINE',
['Vs'] = 'V-LINE',
['\22'] = 'V-BLOCK',
['\22s'] = 'V-BLOCK',
['s'] = 'SELECT',
['S'] = 'S-LINE',
['\19'] = 'S-BLOCK',
['i'] = 'INSERT',
['ic'] = 'INSERT',
['ix'] = 'INSERT',
['R'] = 'REPLACE',
['Rc'] = 'REPLACE',
['Rx'] = 'REPLACE',
['Rv'] = 'V-REPLACE',
['Rvc'] = 'V-REPLACE',
['Rvx'] = 'V-REPLACE',
['c'] = 'COMMAND',
['cv'] = 'EX',
['ce'] = 'EX',
['r'] = 'REPLACE',
['rm'] = 'MORE',
['r?'] = 'CONFIRM',
['!'] = 'SHELL',
['t'] = 'TERMINAL',
}
---@return string current mode name
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

View File

@ -0,0 +1,91 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
-- To provide notices for user
local M = {}
local notices = {}
local persistent_notices = {}
---append new notice
---@param notice string|table table is a list of strings
function M.add_notice(notice)
if type(notice) == 'string' then
notice = vim.split(notice, '\n')
end
if notice[#notice] ~= '' then
notice[#notice + 1] = ''
end
table.insert(notices, notice)
end
---appends persistent notice. These don't get cleared on setup
---@param notice string|table table is a list of strings
function M.add_persistent_notice(notice)
if type(notice) == 'string' then
notice = vim.split(notice, '\n')
end
if not vim.tbl_contains(persistent_notices, notice) then
table.insert(persistent_notices, notice)
end
end
---show setup :LuaLineNotices and show notification about error when there
---are notices available
local notify_done = false
function M.notice_message_startup()
notify_done = false
vim.defer_fn(function()
if notify_done then
return
end
if #notices > 0 or #persistent_notices > 0 then
vim.cmd('command! -nargs=0 LualineNotices lua require"lualine.utils.notices".show_notices()')
vim.notify(
'lualine: There are some issues with your config. Run :LualineNotices for details',
vim.log.levels.WARN,
{}
)
end
notify_done = true
end, 2000)
end
---create notice view
function M.show_notices()
vim.cmd('silent! keepalt split')
local winid = vim.api.nvim_get_current_win()
local bufnr = vim.api.nvim_create_buf(false, true)
vim.api.nvim_win_set_buf(winid, bufnr)
vim.wo[winid].winfixheight = true
vim.wo[winid].winfixwidth = true
vim.wo[winid].number = false
vim.wo[winid].foldcolumn = '0'
vim.wo[winid].relativenumber = false
vim.wo[winid].signcolumn = 'no'
vim.bo[bufnr].filetype = 'markdown'
vim.api.nvim_buf_set_keymap(bufnr, 'n', 'q', '<Cmd>bd<CR>', { noremap = true, silent = true })
local ok, _ = pcall(vim.api.nvim_buf_set_name, 0, 'Lualine Notices')
if not ok then
vim.notify('Lualine Notices is already open in another buffer', vim.log.levels.ERROR, {})
vim.cmd('normal q')
return
end
local notice = vim.tbl_flatten(persistent_notices)
notice = vim.list_extend(notice, vim.tbl_flatten(notices))
vim.fn.appendbufline(bufnr, 0, notice)
vim.fn.deletebufline(bufnr, #notice, vim.fn.line('$'))
vim.api.nvim_win_set_cursor(winid, { 1, 0 })
vim.bo[bufnr].modified = false
vim.bo[bufnr].modifiable = false
end
function M.clear_notices()
notices = {}
end
return M

Some files were not shown because too many files have changed in this diff Show More