doc: improve code documentation (#82)

This commit is contained in:
Shadman 2021-10-12 20:04:47 +06:00 committed by GitHub
parent babc57c62b
commit 08d1340ec9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 354 additions and 98 deletions

View File

@ -13,6 +13,10 @@ local config -- Stores cureently applied config
local new_config = true -- Stores config that will be applied local new_config = true -- Stores config that will be applied
-- Helper for apply_transitional_separators() -- Helper for apply_transitional_separators()
--- finds first applied highlight group fter str_checked in status
---@param status string : unprossed 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) local function find_next_hl(status, str_checked)
-- Gets the next valid hl group from str_checked -- Gets the next valid hl group from str_checked
local hl_pos_start, hl_pos_end = status:find('%%#.-#', str_checked) local hl_pos_start, hl_pos_end = status:find('%%#.-#', str_checked)
@ -32,6 +36,12 @@ local function find_next_hl(status, str_checked)
end end
-- Helper for apply_transitional_separators() -- Helper for apply_transitional_separators()
--- applies transitional separator highlight + transitional separator
---@param status string : unprossed 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 concated separator highlight and transitional separator
local function fill_section_separator(status, str_checked, last_hl, sep, reverse) local function fill_section_separator(status, str_checked, last_hl, sep, reverse)
-- Inserts transitional separator along with transitional highlight -- Inserts transitional separator along with transitional highlight
local next_hl = find_next_hl(status, str_checked) local next_hl = find_next_hl(status, str_checked)
@ -52,6 +62,10 @@ local function fill_section_separator(status, str_checked, last_hl, sep, reverse
end end
end end
--- processes statusline string
--- replaces %s/S{sep} with proper left/right separator highlight + sep
---@param status string : unprossed statusline string
---@return string : processed statusline string
local function apply_transitional_separators(status) local function apply_transitional_separators(status)
local status_applied = {} -- Collects all the pieces for concatation local status_applied = {} -- Collects all the pieces for concatation
local last_hl -- Stores lash highligjt group that we found local last_hl -- Stores lash highligjt group that we found
@ -122,6 +136,11 @@ local function apply_transitional_separators(status)
return table.concat(status_applied) return table.concat(status_applied)
end end
--- creates the statusline string
---@param sections table : section config where components are replaced with
--- component objects
---@param is_focused boolean : whether being evsluated for focused window or not
---@return string statusline string
local function statusline(sections, is_focused) local function statusline(sections, is_focused)
-- The sequence sections should maintain [SECTION_SEQUENCE] -- The sequence sections should maintain [SECTION_SEQUENCE]
local section_sequence = { 'a', 'b', 'c', 'x', 'y', 'z' } local section_sequence = { 'a', 'b', 'c', 'x', 'y', 'z' }
@ -156,7 +175,14 @@ local function statusline(sections, is_focused)
return apply_transitional_separators(table.concat(status)) return apply_transitional_separators(table.concat(status))
end end
-- check if any extension matches the filetype and return proper sections --- 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 evsluated for focused window or not
---@return table : (section_table) section config where components are replaced with
--- component objects
-- TODO: change this so it uses a hash table instead of iteration over lisr
-- to improve redraws. Add buftype / bufname for extensions
-- or some kind of cond ?
local function get_extension_sections(current_ft, is_focused) local function get_extension_sections(current_ft, is_focused)
for _, extension in ipairs(config.extensions) do for _, extension in ipairs(config.extensions) do
for _, filetype in ipairs(extension.filetypes) do for _, filetype in ipairs(extension.filetypes) do
@ -171,6 +197,7 @@ local function get_extension_sections(current_ft, is_focused)
return nil return nil
end end
---@return string statusline string for tabline
local function tabline() local function tabline()
return statusline(config.tabline, true) return statusline(config.tabline, true)
end end
@ -191,6 +218,13 @@ Also provide what colorscheme you're using.
modules.utils_notices.add_notice(string.format(message_template, theme_name)) modules.utils_notices.add_notice(string.format(message_template, theme_name))
end end
--- sets up theme by defining hl groups and setting theme cache in highlight.lua
--- uses options.theme option for theme if it's a string loads theme of that name
--- if it's a table directlybuses it .
--- when theme load fails this fallsback to 'auto' theme if even that fails
--- this falls back to 'gruvbox' theme
--- also sets up auto command to reload lualine on ColorScheme or background
--- change on
local function setup_theme() local function setup_theme()
local function get_theme_from_config() local function get_theme_from_config()
local theme_name = config.options.theme local theme_name = config.options.theme
@ -219,6 +253,7 @@ local function setup_theme()
autocmd lualine OptionSet background lua require'lualine'.setup()]] autocmd lualine OptionSet background lua require'lualine'.setup()]]
end end
--- Sets &tabline option to lualine
local function set_tabline() local function set_tabline()
if next(config.tabline) ~= nil then if next(config.tabline) ~= nil then
vim.go.tabline = "%{%v:lua.require'lualine'.tabline()%}" vim.go.tabline = "%{%v:lua.require'lualine'.tabline()%}"
@ -226,6 +261,8 @@ local function set_tabline()
end end
end end
--- Sets &ststusline option to lualine
--- adds auto command to redraw lualine on VimResized event
local function set_statusline() local function set_statusline()
if next(config.sections) ~= nil or next(config.inactive_sections) ~= nil then if next(config.sections) ~= nil or next(config.inactive_sections) ~= nil then
vim.cmd 'autocmd lualine VimResized * redrawstatus' vim.cmd 'autocmd lualine VimResized * redrawstatus'
@ -234,16 +271,15 @@ local function set_statusline()
end end
end end
local function setup_augroup() --- reloads lualine using new_config
vim.cmd [[augroup lualine | autocmd! | augroup END]]
end
local function reset_lualine() local function reset_lualine()
if package.loaded['lualine.utils.notices'] then if package.loaded['lualine.utils.notices'] then
-- When notices module is not loaded there are no notices to clear.
modules.utils_notices.clear_notices() modules.utils_notices.clear_notices()
end end
setup_augroup() vim.cmd [[augroup lualine | autocmd! | augroup END]]
setup_theme() setup_theme()
-- load components & extensions
modules.loader.load_all(config) modules.loader.load_all(config)
set_statusline() set_statusline()
set_tabline() set_tabline()
@ -253,33 +289,50 @@ local function reset_lualine()
new_config = nil new_config = nil
end end
-- lualine.statusline function
--- Draw correct statusline for current winwow
---@param focused boolean : force the vale of is_focuased . useful for debugginf
---@return string statusline string
local function status_dispatch(focused) local function status_dispatch(focused)
-- disable on specific filetypes local retval
if new_config then if new_config then
-- reload lualine when config was changed
reset_lualine() reset_lualine()
end end
local current_ft = vim.bo.filetype local current_ft = vim.bo.filetype
local is_focused = focused ~= nil and focused or modules.utils.is_focused() local is_focused = focused ~= nil and focused or modules.utils.is_focused()
for _, ft in pairs(config.options.disabled_filetypes) do for _, ft in pairs(config.options.disabled_filetypes) do
-- disable on specific filetypes
if ft == current_ft then if ft == current_ft then
vim.wo.statusline = ''
return '' return ''
end end
end end
local extension_sections = get_extension_sections(current_ft, is_focused) local extension_sections = get_extension_sections(current_ft, is_focused)
if is_focused then if is_focused then
if extension_sections ~= nil then if extension_sections ~= nil then
return statusline(extension_sections, is_focused) retval = statusline(extension_sections, is_focused)
else
retval = statusline(config.sections, is_focused)
end end
return statusline(config.sections, is_focused)
else else
if extension_sections ~= nil then if extension_sections ~= nil then
return statusline(extension_sections, is_focused) retval = statusline(extension_sections, is_focused)
else
retval = statusline(config.inactive_sections, is_focused)
end end
return statusline(config.inactive_sections, is_focused)
end end
return retval
end end
-- lualine.setup function
--- sets new user config
--- This function doesn't load components/theme etc.. they are done before
--- first statusline redraw after new config. This is more efficient when
--- lualine config is done in several setup calls in chunks. This way
--- we don't intialize components just to throgh them away .Instead they are
--- initialized when we know we will use them.
--- sets &last_status tl 2
---@param user_config table table
local function setup(user_config) local function setup(user_config)
new_config = true new_config = true
config = modules.config_module.apply_configuration(user_config) config = modules.config_module.apply_configuration(user_config)

View File

@ -7,6 +7,9 @@ local M = require('lualine.utils.class'):extend()
-- Used to provide a unique id for each component -- Used to provide a unique id for each component
local component_no = 1 local component_no = 1
-- variable to store component output for manipulation
M.status = ''
function M:__tostring() function M:__tostring()
local str = 'Component: ' .. self.options.component_name local str = 'Component: ' .. self.options.component_name
if self.debug then if self.debug then
@ -15,7 +18,8 @@ function M:__tostring()
return str return str
end end
-- Initialize new component ---initialize new component
---@param options table options for component
function M:init(options) function M:init(options)
self.options = options or {} self.options = options or {}
component_no = component_no + 1 component_no = component_no + 1
@ -27,6 +31,8 @@ function M:init(options)
self:create_option_highlights() self:create_option_highlights()
end end
---sets the default separator for component based on whether the component
---is in left sections or right sections when separator option is omited.
function M:set_separator() function M:set_separator()
if self.options.separator == nil then if self.options.separator == nil then
if self.options.component_separators then if self.options.component_separators then
@ -39,6 +45,7 @@ function M:set_separator()
end end
end end
---creates hl group from color option
function M:create_option_highlights() function M:create_option_highlights()
-- set custom highlights -- set custom highlights
if self.options.color then if self.options.color then
@ -50,7 +57,7 @@ function M:create_option_highlights()
end end
end end
-- Adds spaces to left and right of a component ---adds spaces to left and right of a component
function M:apply_padding() function M:apply_padding()
local padding = self.options.padding local padding = self.options.padding
local l_padding, r_padding local l_padding, r_padding
@ -77,7 +84,7 @@ function M:apply_padding()
end end
end end
-- Applies custom highlights for component ---applies custom highlights for component
function M:apply_highlights(default_highlight) function M:apply_highlights(default_highlight)
if self.options.color_highlight then if self.options.color_highlight then
self.status = highlight.component_format_highlight(self.options.color_highlight) .. self.status self.status = highlight.component_format_highlight(self.options.color_highlight) .. self.status
@ -97,15 +104,15 @@ function M:apply_highlights(default_highlight)
end end
end end
-- Apply icon in front of component ---apply icon in front of component (prepemds component with icon)
function M:apply_icon() function M:apply_icon()
if self.options.icons_enabled and self.options.icon then if self.options.icons_enabled and self.options.icon then
self.status = self.options.icon .. ' ' .. self.status self.status = self.options.icon .. ' ' .. self.status
end end
end end
-- Apply separator at end of component only when ---apply separator at end of component only when
-- custom highlights haven't affected background ---custom highlights haven't affected background
function M:apply_separator() function M:apply_separator()
local separator = self.options.separator local separator = self.options.separator
if type(separator) == 'table' then if type(separator) == 'table' then
@ -125,6 +132,7 @@ function M:apply_separator()
end end
end end
---apply transitional separator for the component
function M:apply_section_separators() function M:apply_section_separators()
if type(self.options.separator) ~= 'table' then if type(self.options.separator) ~= 'table' then
return return
@ -138,6 +146,8 @@ function M:apply_section_separators()
end end
end end
---remove separator from tail of this component.
---called by lualine.utils.sections.draw_section to manage unnecessary separators
function M:strip_separator() function M:strip_separator()
if not self.applied_separator then if not self.applied_separator then
self.applied_separator = '' self.applied_separator = ''
@ -147,14 +157,12 @@ function M:strip_separator()
return self.status return self.status
end end
-- variable to store component output for manipulation
M.status = ''
-- Actual function that updates a component. Must be overwritten with component functionality
-- luacheck: push no unused args -- luacheck: push no unused args
---actual function that updates a component. Must be overwritten with component functionality
function M:update_status(is_focused) end function M:update_status(is_focused) end
-- luacheck: pop -- luacheck: pop
-- Driver code of the class ---driver code of the class
function M:draw(default_highlight, is_focused) function M:draw(default_highlight, is_focused)
self.status = '' self.status = ''
self.applied_separator = '' self.applied_separator = ''

View File

@ -16,7 +16,8 @@ local sep = package.config:sub(1, 1)
local file_changed = sep ~= '\\' and vim.loop.new_fs_event() or vim.loop.new_fs_poll() 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 local git_dir_cache = {} -- Stores git paths that we already know of
-- sets git_branch veriable to branch name or commit hash if not on branch ---sets git_branch veriable to branch name or commit hash if not on branch
---@param head_file string full path of .git/HEAD file
local function get_git_head(head_file) local function get_git_head(head_file)
local f_head = io.open(head_file) local f_head = io.open(head_file)
if f_head then if f_head then
@ -32,7 +33,7 @@ local function get_git_head(head_file)
return nil return nil
end end
-- Update branch ---update the current value of git_branch and setup file watch on HEAD file
local function update_branch() local function update_branch()
active_bufnr = tostring(vim.fn.bufnr()) active_bufnr = tostring(vim.fn.bufnr())
file_changed:stop() file_changed:stop()
@ -55,7 +56,9 @@ local function update_branch()
branch_cache[vim.fn.bufnr()] = current_git_branch branch_cache[vim.fn.bufnr()] = current_git_branch
end end
-- returns full path to git directory for dir_path or current directory ---returns full path to git directory for dir_path or current directory
---@param dir_path string|nil
---@return string
function M.find_git_dir(dir_path) function M.find_git_dir(dir_path)
-- get file dir so we can search from that dir -- get file dir so we can search from that dir
local file_dir = dir_path or vim.fn.expand '%:p:h' local file_dir = dir_path or vim.fn.expand '%:p:h'
@ -103,6 +106,7 @@ function M.find_git_dir(dir_path)
return git_dir return git_dir
end end
---initialize git_branch ,odule
function M.init() function M.init()
-- run watch head on load so branch is present when component is loaded -- run watch head on load so branch is present when component is loaded
M.find_git_dir() M.find_git_dir()

View File

@ -1,7 +1,8 @@
local highlight = require 'lualine.highlight' local highlight = require 'lualine.highlight'
local Buffer = require('lualine.utils.class'):extend() local Buffer = require('lualine.utils.class'):extend()
---intialize a new buffer from opts
---@param opts table
function Buffer:init(opts) function Buffer:init(opts)
assert(opts.bufnr, 'Cannot create Buffer without bufnr') assert(opts.bufnr, 'Cannot create Buffer without bufnr')
self.bufnr = opts.bufnr self.bufnr = opts.bufnr
@ -10,6 +11,7 @@ function Buffer:init(opts)
self:get_props() self:get_props()
end end
---setup icons, modified status for buffer
function Buffer:get_props() function Buffer:get_props()
self.file = vim.fn.bufname(self.bufnr) self.file = vim.fn.bufname(self.bufnr)
self.buftype = vim.api.nvim_buf_get_option(self.bufnr, 'buftype') self.buftype = vim.api.nvim_buf_get_option(self.bufnr, 'buftype')
@ -40,21 +42,25 @@ function Buffer:get_props()
self.icon = dev .. ' ' self.icon = dev .. ' '
end end
end end
return self
end end
---returns rendered buffer
---@return string
function Buffer:render() function Buffer:render()
local name local name
if self.ellipse then if self.ellipse then -- show elipsis
name = '...' name = '...'
else else
name = string.format(' %s%s%s ', self.icon, self:name(), self.modified_icon) name = string.format(' %s%s%s ', self.icon, self:name(), self.modified_icon)
end end
self.len = vim.fn.strchars(name) self.len = vim.fn.strchars(name)
-- setup for mouse clicks
local line = string.format('%%%s@LualineSwitchBuffer@%s%%T', self.bufnr, name) local line = string.format('%%%s@LualineSwitchBuffer@%s%%T', self.bufnr, name)
-- apply highlight
line = highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')]) .. line line = highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')]) .. line
-- apply separators
if self.options.self.section < 'lualine_x' and not self.first then if self.options.self.section < 'lualine_x' and not self.first then
local sep_before = self:separator_before() local sep_before = self:separator_before()
line = sep_before .. line line = sep_before .. line
@ -67,6 +73,8 @@ function Buffer:render()
return line return line
end end
---apply separator before current buffer
---@return string
function Buffer:separator_before() function Buffer:separator_before()
if self.current or self.aftercurrent then if self.current or self.aftercurrent then
return '%S{' .. self.options.section_separators.left .. '}' return '%S{' .. self.options.section_separators.left .. '}'
@ -75,6 +83,8 @@ function Buffer:separator_before()
end end
end end
---apply separator after current buffer
---@return string
function Buffer:separator_after() function Buffer:separator_after()
if self.current or self.beforecurrent then if self.current or self.beforecurrent then
return '%s{' .. self.options.section_separators.right .. '}' return '%s{' .. self.options.section_separators.right .. '}'
@ -83,6 +93,8 @@ function Buffer:separator_after()
end end
end end
---returns name of current buffer after filtering special buffers
---@return string
function Buffer:name() function Buffer:name()
if self.options.filetype_names[self.filetype] then if self.options.filetype_names[self.filetype] then
return self.options.filetype_names[self.filetype] return self.options.filetype_names[self.filetype]

View File

@ -22,6 +22,11 @@ local default_options = {
}, },
} }
-- 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 function get_hl(section, is_active)
local suffix = is_active and '_normal' or '_inactive' local suffix = is_active and '_normal' or '_inactive'
local section_redirects = { local section_redirects = {
@ -66,6 +71,8 @@ function M:update_status()
end end
local current_bufnr = vim.fn.bufnr() local current_bufnr = vim.fn.bufnr()
local current = -2 local current = -2
-- mark the first, last, current, before current, after current buffers
-- for rendering
if buffers[1] then if buffers[1] then
buffers[1].first = true buffers[1].first = true
end end
@ -95,6 +102,8 @@ function M:update_status()
current = i current = i
end end
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 if current == -2 then
local b = Buffer { bufnr = vim.fn.bufnr(), options = self.options, highlights = self.highlights } local b = Buffer { bufnr = vim.fn.bufnr(), options = self.options, highlights = self.highlights }
b.current = true b.current = true
@ -127,24 +136,26 @@ function M:update_status()
if before == nil and after == nil then if before == nil and after == nil then
break break
end end
-- draw left most undrawn buffer if fits in max_length
if before then if before then
rendered_before = before:render() rendered_before = before:render()
total_length = total_length + before.len total_length = total_length + before.len
if total_length > max_length then
break
end
table.insert(data, 1, rendered_before)
end end
-- draw right most undrawn buffer if fits in max_length
if after then if after then
rendered_after = after:render() rendered_after = after:render()
total_length = total_length + after.len total_length = total_length + after.len
end if total_length > max_length then
if total_length > max_length then break
break end
end
if before then
table.insert(data, 1, rendered_before)
end
if after then
data[#data + 1] = rendered_after data[#data + 1] = rendered_after
end end
end end
-- draw elipsis (...) on relevent sides if all buffers don't fit in max_length
if total_length > max_length then if total_length > max_length then
if before ~= nil then if before ~= nil then
before.ellipse = true before.ellipse = true

View File

@ -2,6 +2,7 @@ local require = require('lualine_require').require
local utils = require 'lualine.utils.utils' local utils = require 'lualine.utils.utils'
local M = {} local M = {}
-- default symbols for diagnostics component
M.symbols = { M.symbols = {
icons = { icons = {
error = '', -- xf659 error = '', -- xf659
@ -12,6 +13,7 @@ M.symbols = {
no_icons = { error = 'E:', warn = 'W:', info = 'I:', hint = 'H:' }, no_icons = { error = 'E:', warn = 'W:', info = 'I:', hint = 'H:' },
} }
-- default options for diagnostics component
M.options = { M.options = {
colored = true, colored = true,
update_in_insert = false, update_in_insert = false,

View File

@ -69,6 +69,7 @@ function M:update_status()
end end
local error_count, warning_count, info_count, hint_count = 0, 0, 0, 0 local error_count, warning_count, info_count, hint_count = 0, 0, 0, 0
local diagnostic_data = modules.sources.get_diagnostics(self.options.sources) local diagnostic_data = modules.sources.get_diagnostics(self.options.sources)
-- sum all the counts
for _, data in pairs(diagnostic_data) do for _, data in pairs(diagnostic_data) do
error_count = error_count + data.error error_count = error_count + data.error
warning_count = warning_count + data.warn warning_count = warning_count + data.warn
@ -82,6 +83,7 @@ function M:update_status()
info = info_count, info = info_count,
hint = hint_count, hint = hint_count,
} }
-- format the counts with symbols and highlights
if self.options.colored then if self.options.colored then
local colors = {} local colors = {}
for name, hl in pairs(self.highlight_groups) do for name, hl in pairs(self.highlight_groups) do

View File

@ -1,5 +1,8 @@
local M = {} 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 = { M.sources = {
nvim_lsp = function() nvim_lsp = function()
local error_count = vim.lsp.diagnostic.get_count(0, 'Error') local error_count = vim.lsp.diagnostic.get_count(0, 'Error')
@ -45,6 +48,9 @@ M.sources = {
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) M.get_diagnostics = function(sources)
local result = {} local result = {}
for index, source in ipairs(sources) do for index, source in ipairs(sources) do

View File

@ -17,7 +17,8 @@ local diff_job = nil
local active_bufnr = '0' local active_bufnr = '0'
local diff_cache = {} -- Stores last known value of diff of a buffer local diff_cache = {} -- Stores last known value of diff of a buffer
-- initialize the module ---initialize the module
---param opts table
function M.init(opts) function M.init(opts)
if type(opts.source) == 'function' then if type(opts.source) == 'function' then
M.src = opts.source M.src = opts.source
@ -28,14 +29,15 @@ function M.init(opts)
end end
end end
-- Api to get git sign count ---Api to get git sign count
-- scheme : ---scheme :
-- { ---{
-- added = added_count, --- added = added_count,
-- modified = modified_count, --- modified = modified_count,
-- removed = removed_count, --- removed = removed_count,
-- } ---}
-- error_code = { added = -1, modified = -1, removed = -1 } ---error_code = { added = -1, modified = -1, removed = -1 }
---@param bufnr number|nil
function M.get_sign_count(bufnr) function M.get_sign_count(bufnr)
if bufnr then if bufnr then
return diff_cache[bufnr] return diff_cache[bufnr]
@ -52,7 +54,8 @@ function M.get_sign_count(bufnr)
return git_diff return git_diff
end end
-- process diff data and update git_diff{ added, removed, modified } ---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) local function process_diff(data)
-- Adapted from https://github.com/wbthomason/nvim-vcs.lua -- Adapted from https://github.com/wbthomason/nvim-vcs.lua
local added, removed, modified = 0, 0, 0 local added, removed, modified = 0, 0, 0
@ -79,7 +82,7 @@ local function process_diff(data)
git_diff = { added = added, modified = modified, removed = removed } git_diff = { added = added, modified = modified, removed = removed }
end end
-- Updates the job args ---updates the job args
function M.update_diff_args() function M.update_diff_args()
-- Donn't show git diff when current buffer doesn't have a filename -- Donn't show git diff when current buffer doesn't have a filename
active_bufnr = tostring(vim.fn.bufnr()) active_bufnr = tostring(vim.fn.bufnr())
@ -118,7 +121,7 @@ function M.update_diff_args()
M.update_git_diff() M.update_git_diff()
end end
-- Update git_diff veriable ---update git_diff veriable
function M.update_git_diff() function M.update_git_diff()
if M.diff_args then if M.diff_args then
diff_output_cache = {} diff_output_cache = {}

View File

@ -9,10 +9,18 @@ local default_options = {
shorting_target = 40, shorting_target = 40,
} }
---counts how many times pattern occur in base ( used for counting path-sep )
---@param base string
---@param pattern string
---@return number
local function count(base, pattern) local function count(base, pattern)
return select(2, string.gsub(base, pattern, '')) return select(2, string.gsub(base, pattern, ''))
end end
---shortens path by turning apple/orange -> a/orange
---@param path string
---@param sep string path separator
---@return string
local function shorten_path(path, sep) local function shorten_path(path, sep)
-- ('([^/])[^/]+%/', '%1/', 1) -- ('([^/])[^/]+%/', '%1/', 1)
return path:gsub(string.format('([^%s])[^%s]+%%%s', sep, sep, sep), '%1' .. sep, 1) return path:gsub(string.format('([^%s])[^%s]+%%%s', sep, sep, sep), '%1' .. sep, 1)

View File

@ -23,12 +23,18 @@ function M:update_status()
return status return status
end end
---evaluate the lua code and return it's result as string
---@param code string
---@return string
function M.lua_eval(code) function M.lua_eval(code)
local result = loadstring('return ' .. code)() local result = loadstring('return ' .. code)()
assert(result, 'String expected got nil') assert(result, 'String expected got nil')
return tostring(result) return tostring(result)
end end
---call vim function (name) and return it's result as string
---@param name string
---@return string
function M.vim_function(name) function M.vim_function(name)
-- vim function component -- vim function component
local ok, return_val = pcall(vim.api.nvim_call_function, name, {}) local ok, return_val = pcall(vim.api.nvim_call_function, name, {})

View File

@ -14,6 +14,11 @@ local default_options = {
}, },
} }
-- 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 function get_hl(section, is_active)
local suffix = is_active and '_normal' or '_inactive' local suffix = is_active and '_normal' or '_inactive'
local section_redirects = { local section_redirects = {
@ -55,6 +60,8 @@ function M:update_status()
for t = 1, vim.fn.tabpagenr '$' do for t = 1, vim.fn.tabpagenr '$' do
tabs[#tabs + 1] = Tab { tabnr = t, options = self.options, highlights = self.highlights } tabs[#tabs + 1] = Tab { tabnr = t, options = self.options, highlights = self.highlights }
end end
-- mark the first, last, current, before current, after current tabpages
-- for rendering
local current = vim.fn.tabpagenr() local current = vim.fn.tabpagenr()
tabs[1].first = true tabs[1].first = true
tabs[#tabs].last = true tabs[#tabs].last = true
@ -79,7 +86,9 @@ function M:update_status()
end end
end end
local current_tab = tabs[current] local current_tab = tabs[current]
if current_tab == nil then -- 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 redundent code
local t = Tab { tabnr = vim.fn.tabpagenr(), options = self.options, highlights = self.highlights } local t = Tab { tabnr = vim.fn.tabpagenr(), options = self.options, highlights = self.highlights }
t.current = true t.current = true
t.last = true t.last = true
@ -97,6 +106,7 @@ function M:update_status()
if before == nil and after == nil then if before == nil and after == nil then
break break
end end
-- draw left most undrawn tab if fits in max_length
if before then if before then
rendered_before = before:render() rendered_before = before:render()
total_length = total_length + before.len total_length = total_length + before.len
@ -105,6 +115,7 @@ function M:update_status()
end end
table.insert(data, 1, rendered_before) table.insert(data, 1, rendered_before)
end end
-- draw right most undrawn tab if fits in max_length
if after then if after then
rendered_after = after:render() rendered_after = after:render()
total_length = total_length + after.len total_length = total_length + after.len
@ -114,6 +125,7 @@ function M:update_status()
data[#data + 1] = rendered_after data[#data + 1] = rendered_after
end end
end end
-- draw elipsis (...) on relevent sides if all tabs don't fit in max_length
if total_length > max_length then if total_length > max_length then
if before ~= nil then if before ~= nil then
before.ellipse = true before.ellipse = true

View File

@ -1,6 +1,8 @@
local highlight = require 'lualine.highlight' local highlight = require 'lualine.highlight'
local Tab = require('lualine.utils.class'):extend() local Tab = require('lualine.utils.class'):extend()
---intialize a new tab from opts
---@param opts table
function Tab:init(opts) function Tab:init(opts)
assert(opts.tabnr, 'Cannot create Tab without tabnr') assert(opts.tabnr, 'Cannot create Tab without tabnr')
self.tabnr = opts.tabnr self.tabnr = opts.tabnr
@ -8,6 +10,9 @@ function Tab:init(opts)
self.highlights = opts.highlights self.highlights = opts.highlights
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() function Tab:label()
local buflist = vim.fn.tabpagebuflist(self.tabnr) local buflist = vim.fn.tabpagebuflist(self.tabnr)
local winnr = vim.fn.tabpagewinnr(self.tabnr) local winnr = vim.fn.tabpagewinnr(self.tabnr)
@ -27,11 +32,14 @@ function Tab:label()
return vim.fn.fnamemodify(file, ':t') return vim.fn.fnamemodify(file, ':t')
end end
---returns rendered tab
---@return string
function Tab:render() function Tab:render()
local name local name
if self.ellipse then if self.ellipse then -- show elipsis
name = '...' name = '...'
else else
-- different formats for different modes
if self.options.mode == 0 then if self.options.mode == 0 then
name = string.format('%s%s ', (self.last or not self.first) and ' ' or '', tostring(self.tabnr)) name = string.format('%s%s ', (self.last or not self.first) and ' ' or '', tostring(self.tabnr))
elseif self.options.mode == 1 then elseif self.options.mode == 1 then
@ -40,10 +48,14 @@ function Tab:render()
name = string.format('%s%s %s ', (self.last or not self.first) and ' ' or '', tostring(self.tabnr), self:label()) name = string.format('%s%s %s ', (self.last or not self.first) and ' ' or '', tostring(self.tabnr), self:label())
end end
end end
self.len = #name self.len = vim.fn.strchars(name)
-- setup for mouse clicks
local line = string.format('%%%s@LualineSwitchTab@%s%%T', self.tabnr, name) local line = string.format('%%%s@LualineSwitchTab@%s%%T', self.tabnr, name)
-- apply highlight
line = highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')]) .. line line = highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')]) .. line
-- apply separators
if self.options.self.section < 'lualine_x' and not self.first then if self.options.self.section < 'lualine_x' and not self.first then
local sep_before = self:separator_before() local sep_before = self:separator_before()
line = sep_before .. line line = sep_before .. line
@ -56,6 +68,8 @@ function Tab:render()
return line return line
end end
---apply separator before current tab
---@return string
function Tab:separator_before() function Tab:separator_before()
if self.current or self.aftercurrent then if self.current or self.aftercurrent then
return '%S{' .. self.options.section_separators.left .. '}' return '%S{' .. self.options.section_separators.left .. '}'
@ -64,6 +78,8 @@ function Tab:separator_before()
end end
end end
---apply separator after current tab
---@return string
function Tab:separator_after() function Tab:separator_after()
if self.current or self.beforecurrent then if self.current or self.beforecurrent then
return '%s{' .. self.options.section_separators.right .. '}' return '%s{' .. self.options.section_separators.right .. '}'

View File

@ -29,7 +29,9 @@ local config = {
extensions = {}, extensions = {},
} }
-- change separator format 'x' to {left='x', right='x'} --- change separator format 'x' to {left='x', right='x'}
---@param separators string|table
---@return table
local function fix_separators(separators) local function fix_separators(separators)
if separators ~= nil then if separators ~= nil then
if type(separators) == 'string' then if type(separators) == 'string' then
@ -39,6 +41,9 @@ local function fix_separators(separators)
return separators return separators
end end
---extends config based on configtable
---@param config_table table
---@return table copy of config
local function apply_configuration(config_table) local function apply_configuration(config_table)
if not config_table then if not config_table then
return vim.deepcopy(config) return vim.deepcopy(config)
@ -63,6 +68,8 @@ local function apply_configuration(config_table)
return vim.deepcopy(config) return vim.deepcopy(config)
end end
--- returns current active config
---@return table a copy of config
local function get_current_config() local function get_current_config()
return vim.deepcopy(config) return vim.deepcopy(config)
end end

View File

@ -33,12 +33,14 @@ local mode_to_highlight = {
['TERMINAL'] = '_terminal', ['TERMINAL'] = '_terminal',
} }
-- determine if an highlight exist and isn't cleared --- 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) function M.highlight_exists(highlight_name)
return loaded_highlights[highlight_name] or false return loaded_highlights[highlight_name] or false
end end
-- clears loaded_highlights table and highlights --- clears loaded_highlights table and highlights
local function clear_highlights() local function clear_highlights()
for highlight_name, _ in pairs(loaded_highlights) do for highlight_name, _ in pairs(loaded_highlights) do
vim.cmd('highlight clear ' .. highlight_name) vim.cmd('highlight clear ' .. highlight_name)
@ -46,6 +48,9 @@ local function clear_highlights()
end end
end end
---converts cterm, color_name type colors to #rrggbb format
---@param color string|number
---@return string
local function sanitize_color(color) local function sanitize_color(color)
if type(color) == 'string' then if type(color) == 'string' then
if color:sub(1, 1) == '#' then if color:sub(1, 1) == '#' then
@ -60,6 +65,12 @@ local function sanitize_color(color)
end end
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 ect
---@param link string hl_group name to link new hl to
function M.highlight(name, foreground, background, gui, link) function M.highlight(name, foreground, background, gui, link)
local command = { 'highlight!' } local command = { 'highlight!' }
if link and #link > 0 then if link and #link > 0 then
@ -68,13 +79,13 @@ function M.highlight(name, foreground, background, gui, link)
foreground = sanitize_color(foreground) foreground = sanitize_color(foreground)
background = sanitize_color(background) background = sanitize_color(background)
table.insert(command, name) table.insert(command, name)
if foreground and foreground ~= 'none' then if foreground and foreground ~= 'None' then
table.insert(command, 'guifg=' .. foreground) table.insert(command, 'guifg=' .. foreground)
if create_cterm_colors then if create_cterm_colors then
table.insert(command, 'ctermfg=' .. modules.color_utils.rgb2cterm(foreground)) table.insert(command, 'ctermfg=' .. modules.color_utils.rgb2cterm(foreground))
end end
end end
if background and background ~= 'none' then if background and background ~= 'None' then
table.insert(command, 'guibg=' .. background) table.insert(command, 'guibg=' .. background)
if create_cterm_colors then if create_cterm_colors then
table.insert(command, 'ctermbg=' .. modules.color_utils.rgb2cterm(background)) table.insert(command, 'ctermbg=' .. modules.color_utils.rgb2cterm(background))
@ -89,6 +100,8 @@ function M.highlight(name, foreground, background, gui, link)
loaded_highlights[name] = true loaded_highlights[name] = true
end end
---define hl_groups for a theme
---@param theme table
function M.create_highlight_groups(theme) function M.create_highlight_groups(theme)
clear_highlights() clear_highlights()
active_theme = theme active_theme = theme
@ -105,9 +118,9 @@ function M.create_highlight_groups(theme)
end end
end end
-- @description: adds '_mode' at end of highlight_group ---@description: adds '_mode' at end of highlight_group
-- @param highlight_group:(string) name of highlight group ---@param highlight_group string name of highlight group
-- @return: (string) highlight group name with mode ---@return string highlight group name with mode
function M.append_mode(highlight_group, is_focused) function M.append_mode(highlight_group, is_focused)
if is_focused == nil then if is_focused == nil then
is_focused = modules.utils.is_focused() is_focused = modules.utils.is_focused()
@ -120,12 +133,12 @@ function M.append_mode(highlight_group, is_focused)
end end
-- Helper function for create component highlight -- Helper function for create component highlight
-- Handles fall back of colors when crea58ng highlight group ---Handles fall back of colors when creating highlight group
-- @param color table color passed for creating component highlight ---@param color table color passed for creating component highlight
-- @param options_color color set by color option for component ---@param options_color table color set by color option for component
-- this is first falk back --- this is first fall back
-- @param default_color Colors et in theme this is 2nd fall back ---@param default_color table colors et in theme this is 2nd fall back
-- @param kind (fg/bg)) ---@param kind string fg/bg
local function get_default_component_color(color, options_color, default_color, kind) local function get_default_component_color(color, options_color, default_color, kind)
if color[kind] then if color[kind] then
return color[kind] return color[kind]
@ -144,15 +157,15 @@ local function get_default_component_color(color, options_color, default_color,
end end
end end
-- Create highlight group with fg bg and gui from theme ---Create highlight group with fg bg and gui from theme
-- @color has to be { fg = "#rrggbb", bg="#rrggbb" gui = "effect" } ---@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 --- all the color elements are optional if fg or bg is not given options
-- So fg and bg can default the themes colors --- must be provided So fg and bg can default the themes colors
-- @highlight_tag is unique tag for highlight group ---@param highlight_tag string is unique tag for highlight group
-- returns the name of highlight group ---returns the name of highlight group
-- @options is parameter of component.init() function ---@param options table is parameter of component.init() function
-- @return: (string) unique name that can be used by component_format_highlight ---@return string unique name that can be used by component_format_highlight
-- to retrive highlight group --- to retrieve highlight group
function M.create_component_highlight_group(color, highlight_tag, options) function M.create_component_highlight_group(color, highlight_tag, options)
local tag_id = 0 local tag_id = 0
while while
@ -211,11 +224,11 @@ function M.create_component_highlight_group(color, highlight_tag, options)
return options.self.section .. '_' .. highlight_tag return options.self.section .. '_' .. highlight_tag
end end
-- @description: retrieve highlight_groups for components ---@description: retrieve highlight_groups for components
-- @param highlight_name:(string) highlight group name without mode ---@param highlight_name string highlight group name without mode
-- return value of create_component_highlight_group is to be passed in --- return value of create_component_highlight_group is to be passed in
-- this parameter to receive highlight that was created --- this parameter to receive highlight that was created
-- @return: (string) formated highlight group name ---@return string formatted highlight group name
function M.component_format_highlight(highlight_name) function M.component_format_highlight(highlight_name)
local highlight_group = highlight_name local highlight_group = highlight_name
if highlight_name:find 'no_mode' == #highlight_name - #'no_mode' + 1 then if highlight_name:find 'no_mode' == #highlight_name - #'no_mode' + 1 then
@ -229,6 +242,12 @@ function M.component_format_highlight(highlight_name)
end end
end end
---@description: retrieve highlight_groups for section
---@param highlight_group 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(highlight_group, is_focused) function M.format_highlight(highlight_group, is_focused)
if highlight_group > 'lualine_c' and not M.highlight_exists(highlight_group .. '_normal') then if highlight_group > 'lualine_c' and not M.highlight_exists(highlight_group .. '_normal') then
highlight_group = 'lualine_' .. section_highlight_map[highlight_group:match 'lualine_(.)'] highlight_group = 'lualine_' .. section_highlight_map[highlight_group:match 'lualine_(.)']
@ -241,11 +260,11 @@ function M.format_highlight(highlight_group, is_focused)
return '%#' .. highlight_group .. '_normal#' return '%#' .. highlight_group .. '_normal#'
end end
-- @description : Provides transitional highlights for section separators. ---@description : Provides transitional highlights for section separators.
-- @param left_hl :(string) this highlights bg is used for fg of transitional hl ---@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 ---@param right_hl string this highlights bg is used for bg of transitional hl
-- '▶️' and '◀️' ' eeds reverse colors so the caller should swap left and right --- '▶️' and '◀️' ' needs reverse colors so the caller should swap left and right
-- @return: (string) formated highlight group name ---@return string formatted highlight group name
function M.get_transitional_highlights(left_hl, right_hl) function M.get_transitional_highlights(left_hl, right_hl)
-- When both left and right highlights are same or one is absent -- When both left and right highlights are same or one is absent
-- nothing to transition to. -- nothing to transition to.
@ -253,7 +272,7 @@ function M.get_transitional_highlights(left_hl, right_hl)
return nil return nil
end end
-- construct the name of hightlight group -- construct the name of highlight group
local highlight_name = table.concat({ 'lualine_transitional', left_hl, 'to', right_hl }, '_') local highlight_name = table.concat({ 'lualine_transitional', left_hl, 'to', right_hl }, '_')
if not M.highlight_exists(highlight_name) then if not M.highlight_exists(highlight_name) then
-- Create the highlight_group if needed -- Create the highlight_group if needed

View File

@ -4,11 +4,11 @@ local Object = {}
Object.__index = Object Object.__index = Object
-- luacheck: push no unused args -- luacheck: push no unused args
-- Initializer ---Initializer
function Object:init(...) end function Object:init(...) end
-- luacheck: pop -- luacheck: pop
-- Extened base class to create a child class ---Extened base class to create a child class
function Object:extend() function Object:extend()
local cls = {} local cls = {}
for k, v in pairs(self) do for k, v in pairs(self) do
@ -28,14 +28,14 @@ function Object:__tostring()
end end
-- luacheck: pop -- luacheck: pop
-- Creates a new object ---Creates a new object
function Object:new(...) function Object:new(...)
local obj = setmetatable({}, self) local obj = setmetatable({}, self)
obj:init(...) obj:init(...)
return obj return obj
end end
-- Creates a new object ---Creates a new object
function Object:__call(...) function Object:__call(...)
return self:new(...) return self:new(...)
end end

View File

@ -274,6 +274,9 @@ local color_table = {
} }
-- stylua: ignore end -- stylua: ignore end
---converts #rrggbb fomated color to cterm ('0'-'255') color
---@param hex_color string
---@return string
function M.rgb2cterm(hex_color) function M.rgb2cterm(hex_color)
local function get_color_distance(color1, color2) local function get_color_distance(color1, color2)
-- returns how much color2 deviates from color1 -- returns how much color2 deviates from color1
@ -300,6 +303,9 @@ function M.rgb2cterm(hex_color)
return closest_cterm_color return closest_cterm_color
end end
---converts color name (only ones supported by neovim) formated colors to #rrggbb
---@param name string like red,green,grey
---@return string
function M.color_name2rgb(name) function M.color_name2rgb(name)
local color_val = vim.api.nvim_get_color_by_name(name) local color_val = vim.api.nvim_get_color_by_name(name)
if color_val == -1 then if color_val == -1 then
@ -308,6 +314,9 @@ function M.color_name2rgb(name)
return string.format('#%06x', color_val) return string.format('#%06x', color_val)
end end
---converts cterm(0-255) to #rrggbb
---@param color number
---@return string
function M.cterm2rgb(color) function M.cterm2rgb(color)
local color_data = color_table[color + 1] local color_data = color_table[color + 1]
if color_data ~= nil then if color_data ~= nil then

View File

@ -1,12 +1,15 @@
-- Copyright (c) 2020-2021 shadmansaleh -- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details. -- MIT license, see LICENSE for more details.
-- Wrapper arround job api --- wrapper arround job api
--- creates a job handler when called
local Job = setmetatable({ local Job = setmetatable({
--- start the job
start = function(self) start = function(self)
self.job_id = vim.fn.jobstart(self.args.cmd, self.args) self.job_id = vim.fn.jobstart(self.args.cmd, self.args)
return self.job_id > 0 return self.job_id > 0
end, end,
--- stop the job. also imidiately disables io from the job.
stop = function(self) stop = function(self)
if self.killed then if self.killed then
return return
@ -30,6 +33,10 @@ local Job = setmetatable({
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) __call = function(self, args)
args = vim.deepcopy(args or {}) args = vim.deepcopy(args or {})
if type(args.cmd) == 'string' then if type(args.cmd) == 'string' then

View File

@ -7,13 +7,15 @@ local modules = lualine_require.lazy_require {
notice = 'lualine.utils.notices', notice = 'lualine.utils.notices',
} }
local is_valid_filename = lualine_require.is_valid_filename local is_valid_filename = lualine_require.is_valid_filename
local sep = lualine_require.sep local sep = lualine_require.sep
--- function that loads specific type of component
local component_types = { local component_types = {
--- loads lua functions as component
lua_fun = function(component) lua_fun = function(component)
return require 'lualine.components.special.function_component'(component) return require 'lualine.components.special.function_component'(component)
end, end,
--- loads lua modules as components (ones in /lua/lualine/components/)
mod = function(component) mod = function(component)
local ok, loaded_component = pcall(require, 'lualine.components.' .. component[1]) local ok, loaded_component = pcall(require, 'lualine.components.' .. component[1])
if ok then if ok then
@ -27,6 +29,7 @@ local component_types = {
return loaded_component return loaded_component
end end
end, end,
--- loads builtin statusline patterns as component
stl = function(component) stl = function(component)
local stl_expr = component[1] -- Vim's %p %l statusline elements local stl_expr = component[1] -- Vim's %p %l statusline elements
component[1] = function() component[1] = function()
@ -34,14 +37,19 @@ local component_types = {
end end
return require 'lualine.components.special.function_component'(component) return require 'lualine.components.special.function_component'(component)
end, end,
--- loads variables & options (g:,go:,b:,bo:...) as componenta
var = function(component) var = function(component)
return require 'lualine.components.special.vim_var_component'(component) return require 'lualine.components.special.vim_var_component'(component)
end, end,
--- loads vim functions and lua expressions as components
['_'] = function(component) ['_'] = function(component)
return require 'lualine.components.special.eval_func_component'(component) return require 'lualine.components.special.eval_func_component'(component)
end, end,
} }
---load a component from component confif
---@param component table component + component options
---@return table the loaded & initialized component
local function component_loader(component) local function component_loader(component)
if type(component[1]) == 'function' then if type(component[1]) == 'function' then
return component_types.lua_fun(component) return component_types.lua_fun(component)
@ -114,6 +122,9 @@ You'll have to change it to this to retain old behavior:
end end
end 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) local function load_sections(sections, options)
for section_name, section in pairs(sections) do for section_name, section in pairs(sections) do
for index, component in pairs(section) do for index, component in pairs(section) do
@ -130,12 +141,16 @@ local function load_sections(sections, options)
end end
end end
---loads all the configs (active, inactive, tabline)
---@param config table user config
local function load_components(config) local function load_components(config)
load_sections(config.sections, config.options) load_sections(config.sections, config.options)
load_sections(config.inactive_sections, config.options) load_sections(config.inactive_sections, config.options)
load_sections(config.tabline, config.options) load_sections(config.tabline, config.options)
end end
---loads all the extensions
---@param config table user confif
local function load_extensions(config) local function load_extensions(config)
local loaded_extensions = {} local loaded_extensions = {}
for _, extension in pairs(config.extensions) do for _, extension in pairs(config.extensions) do
@ -175,11 +190,17 @@ Extension named `%s` was not found . Check if spelling is correct.
config.extensions = loaded_extensions config.extensions = loaded_extensions
end end
---loads sections and extensions or entire user config
---@param config table user config
local function load_all(config) local function load_all(config)
load_components(config) load_components(config)
load_extensions(config) load_extensions(config)
end end
---loads a theme from lua module
---priotizes external themes (from user config or other plugins) over the bundled ones
---@param theme_name string
---@return table theme defination from module
local function load_theme(theme_name) local function load_theme(theme_name)
assert(is_valid_filename(theme_name), 'Invalid filename') assert(is_valid_filename(theme_name), 'Invalid filename')
local retval local retval

View File

@ -1,6 +1,7 @@
-- Copyright (c) 2020-2021 hoob3rt -- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details. -- MIT license, see LICENSE for more details.
local Mode = {} local Mode = {}
-- stylua: ignore -- stylua: ignore
Mode.map = { Mode.map = {
['n'] = 'NORMAL', ['n'] = 'NORMAL',
@ -40,6 +41,7 @@ Mode.map = {
['t'] = 'TERMINAL', ['t'] = 'TERMINAL',
} }
---@return string current mode name
function Mode.get_mode() function Mode.get_mode()
local mode_code = vim.api.nvim_get_mode().mode local mode_code = vim.api.nvim_get_mode().mode
if Mode.map[mode_code] == nil then if Mode.map[mode_code] == nil then

View File

@ -6,6 +6,8 @@ local M = {}
local notices = {} local notices = {}
local persistent_notices = {} local persistent_notices = {}
---append new notice
---@param notice string|table table is a list of strings
function M.add_notice(notice) function M.add_notice(notice)
if type(notice) == 'string' then if type(notice) == 'string' then
notice = vim.split(notice, '\n') notice = vim.split(notice, '\n')
@ -13,6 +15,8 @@ function M.add_notice(notice)
table.insert(notices, notice) table.insert(notices, notice)
end 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) function M.add_persistent_notice(notice)
if type(notice) == 'string' then if type(notice) == 'string' then
notice = vim.split(notice, '\n') notice = vim.split(notice, '\n')
@ -22,6 +26,8 @@ function M.add_persistent_notice(notice)
end end
end end
---show setup :LuaLineNotices and show notification about error when there
---are notices available
function M.notice_message_startup() function M.notice_message_startup()
if #notices > 0 or #persistent_notices then if #notices > 0 or #persistent_notices then
vim.cmd 'command! -nargs=0 LualineNotices lua require"lualine.utils.notices".show_notices()' vim.cmd 'command! -nargs=0 LualineNotices lua require"lualine.utils.notices".show_notices()'
@ -35,6 +41,7 @@ function M.notice_message_startup()
end end
end end
---create notice view
function M.show_notices() function M.show_notices()
vim.cmd 'silent! keepalt split' vim.cmd 'silent! keepalt split'
@ -54,7 +61,7 @@ function M.show_notices()
local ok, _ = pcall(vim.api.nvim_buf_set_name, 0, 'Lualine Notices') local ok, _ = pcall(vim.api.nvim_buf_set_name, 0, 'Lualine Notices')
if not ok then if not ok then
vim.notify('Lualine Notices is already open in another window', vim.log.levels.ERROR, {}) vim.notify('Lualine Notices is already open in another buffer', vim.log.levels.ERROR, {})
vim.cmd 'normal q' vim.cmd 'normal q'
return return
end end

View File

@ -4,7 +4,16 @@ local M = {}
local require = require('lualine_require').require local require = require('lualine_require').require
local utils = require 'lualine.utils.utils' local utils = require 'lualine.utils.utils'
local highlight = require 'lualine.highlight' local highlight = require 'lualine.highlight'
-- Returns formated string for a section
---runs draw function on components in section
---handles separator edge cases :/
---also handles default transitional separators at section boundaries
---(why? I don't know)
---@param section table list of components
---@param section_name string used for getting proper hl
---@param is_focused boolean
---@return string formated string for a section
--TODO Clean this up this does lots of messy stuff.
function M.draw_section(section, section_name, is_focused) function M.draw_section(section, section_name, is_focused)
local highlight_name = highlight.format_highlight('lualine_' .. section_name, is_focused) local highlight_name = highlight.format_highlight('lualine_' .. section_name, is_focused)

View File

@ -4,6 +4,10 @@ local M = {}
-- Note for now only works for termguicolors scope can be bg or fg or any other -- Note for now only works for termguicolors scope can be bg or fg or any other
-- attr parameter like bold/italic/reverse -- attr parameter like bold/italic/reverse
---@param color_group string hl_group name
---@param scope string bg | fg
---@return table|string returns #rrggbb formated color when scope is specified
---- or comolete color table when scope isn't specified
function M.extract_highlight_colors(color_group, scope) function M.extract_highlight_colors(color_group, scope)
if vim.fn.hlexists(color_group) == 0 then if vim.fn.hlexists(color_group) == 0 then
return nil return nil
@ -23,8 +27,12 @@ function M.extract_highlight_colors(color_group, scope)
return color return color
end end
-- retrives color value from highlight group name in syntax_list --- retrives color value from highlight group name in syntax_list
-- first present highlight is returned --- first present highlight is returned
---@param scope string
---@param syntaxlist table
---@param default string
---@return string|nil
function M.extract_color_from_hllist(scope, syntaxlist, default) function M.extract_color_from_hllist(scope, syntaxlist, default)
for _, highlight_name in ipairs(syntaxlist) do for _, highlight_name in ipairs(syntaxlist) do
if vim.fn.hlexists(highlight_name) ~= 0 then if vim.fn.hlexists(highlight_name) ~= 0 then
@ -44,7 +52,9 @@ function M.extract_color_from_hllist(scope, syntaxlist, default)
return default return default
end end
-- remove empty strings from list ---remove empty strings from list
---@param list table
---@return table
function M.list_shrink(list) function M.list_shrink(list)
local new_list = {} local new_list = {}
for i = 1, #list do for i = 1, #list do
@ -55,12 +65,19 @@ function M.list_shrink(list)
return new_list return new_list
end end
-- Check if a auto command is already defined --- Check if a auto command is already defined
---@param event string
---@param patern string
---@param command_str string
---@return boolean whether autocmd is already defined
local function autocmd_is_defined(event, patern, command_str) local function autocmd_is_defined(event, patern, command_str)
return vim.api.nvim_exec(string.format('au lualine %s %s', event, patern), true):find(command_str) ~= nil return vim.api.nvim_exec(string.format('au lualine %s %s', event, patern), true):find(command_str) ~= nil
end end
-- Define a auto command if it's not already defined --- Define a auto command if it's not already defined
---@param event string event name
---@param patern string event patern
---@param cmd string command to run on event
function M.define_autocmd(event, patern, cmd) function M.define_autocmd(event, patern, cmd)
if not cmd then if not cmd then
cmd = patern cmd = patern
@ -76,6 +93,10 @@ function M.is_focused()
return tonumber(vim.g.actual_curwin) == vim.fn.win_getid() return tonumber(vim.g.actual_curwin) == vim.fn.win_getid()
end end
--- Check what's the charecter at pos
---@param str string
---@param pos number
---@return string charecter at position pos in string str
function M.charAt(str, pos) function M.charAt(str, pos)
return string.char(str:byte(pos)) return string.char(str:byte(pos))
end end

View File

@ -4,6 +4,7 @@ local M = {}
M.sep = package.config:sub(1, 1) M.sep = package.config:sub(1, 1)
-- Figures ou full path of lualine installation
local source = debug.getinfo(1, 'S').source local source = debug.getinfo(1, 'S').source
if source:sub(1, 1) == '@' then if source:sub(1, 1) == '@' then
local base_start = source:find(table.concat({ 'lualine.nvim', 'lua', 'lualine_require.lua' }, M.sep)) local base_start = source:find(table.concat({ 'lualine.nvim', 'lua', 'lualine_require.lua' }, M.sep))
@ -15,11 +16,17 @@ if source:sub(1, 1) == '@' then
end end
end end
--- checks if name is valied
---@param name string
---@return boolean
function M.is_valid_filename(name) function M.is_valid_filename(name)
local invalid_chars = '[^a-zA-Z0-9_. -]' local invalid_chars = '[^a-zA-Z0-9_. -]'
return name:find(invalid_chars) == nil return name:find(invalid_chars) == nil
end end
---require module module
---@param module string mogule arraived
---@return any the required module
function M.require(module) function M.require(module)
if package.loaded[module] then if package.loaded[module] then
return package.loaded[module] return package.loaded[module]
@ -61,6 +68,10 @@ function M.require(module)
return require(module) return require(module)
end end
---requires modules when they are used
---@param modules table k-v table where v is module path and k is name that will
--- be indexed
---@return table metatable where when a key is indexed it gets required and cached
function M.lazy_require(modules) function M.lazy_require(modules)
return setmetatable({}, { return setmetatable({}, {
__index = function(self, key) __index = function(self, key)