perf: Improve startup by droping most of the requires + refactors

Important: It's no longer guaranteed that if component/extension
of same name exists in multiple entries in rtp which one will be
loaded. The guarantee is still there for themes . Means other
plugins or users config can overwrite a lualines internal theme
with same file name . I'm droping the guarantee for components
and extensions because there isn't much usecase for it . It's simple
to have a unique name and droping that guarantee allows more
optimizations that speeds up lualine.
This commit is contained in:
shadmansaleh 2021-08-30 17:54:23 +06:00
parent 2b90200998
commit 1439ba6d37
10 changed files with 153 additions and 136 deletions

View File

@ -1,12 +1,13 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local modules = require('lualine.utils.lazy_require'){
local lualine_require = require'lualine_require'
local modules = lualine_require.lazy_require{
highlight = 'lualine.highlight',
utils = 'lualine.utils.utils',
utils_notices = 'lualine.utils.notices',
}
local Diagnostics = require('lualine.component'):new()
local Diagnostics = lualine_require.require('lualine.component'):new()
-- LuaFormatter off
Diagnostics.default_colors = {

View File

@ -1,11 +1,14 @@
-- Copyright (c) 2020-2021 shadmansaleh
-- MIT license, see LICENSE for more details.
local utils = require 'lualine.utils.utils'
local utils_notices = require('lualine.utils.notices')
local highlight = require 'lualine.highlight'
local Job = require'lualine.utils.job'
local Diff = require('lualine.component'):new()
local lualine_require = require'lualine_require'
local modules = lualine_require.lazy_require{
utils = 'lualine.utils.utils',
utils_notices = 'lualine.utils.notices',
highlight = 'lualine.highlight',
Job = 'lualine.utils.job',
}
local Diff = lualine_require.require('lualine.component'):new()
-- Vars
-- variable to store git diff stats
@ -25,7 +28,7 @@ Diff.default_colors = {
local diff_cache = {} -- Stores last known value of diff of a buffer
local function color_deprecation_notice(color, opt_name)
utils_notices.add_notice(string.format([[
modules.utils_notices.add_notice(string.format([[
### Diff component
Using option `%s` as string to set foreground color has been deprecated
and will soon be removed. Now this option has same semantics as regular
@ -64,7 +67,7 @@ Diff.new = function(self, options, child)
-- apply colors
if not new_instance.options.color_added then
new_instance.options.color_added = {fg =
utils.extract_highlight_colors('DiffAdd', 'fg') or
modules.utils.extract_highlight_colors('DiffAdd', 'fg') or
Diff.default_colors.added}
elseif type(new_instance.options.color_added) == 'string'
and vim.fn.hlexists(new_instance.options.color_added) == 0 then
@ -73,7 +76,7 @@ Diff.new = function(self, options, child)
end
if not new_instance.options.color_modified then
new_instance.options.color_modified = {fg =
utils.extract_highlight_colors('DiffChange', 'fg') or
modules.utils.extract_highlight_colors('DiffChange', 'fg') or
Diff.default_colors.modified}
elseif type(new_instance.options.color_modified) == 'string'
and vim.fn.hlexists(new_instance.options.color_modified) == 0 then
@ -82,7 +85,7 @@ Diff.new = function(self, options, child)
end
if not new_instance.options.color_removed then
new_instance.options.color_removed = {fg =
utils.extract_highlight_colors('DiffDelete', 'fg') or
modules.utils.extract_highlight_colors('DiffDelete', 'fg') or
Diff.default_colors.removed}
elseif type(new_instance.options.color_removed) == 'string'
and vim.fn.hlexists(new_instance.options.color_removed) == 0 then
@ -93,13 +96,13 @@ Diff.new = function(self, options, child)
-- create highlights and save highlight_name in highlights table
if new_instance.options.colored then
new_instance.highlights = {
added = highlight.create_component_highlight_group(
added = modules.highlight.create_component_highlight_group(
new_instance.options.color_added, 'diff_added',
new_instance.options),
modified = highlight.create_component_highlight_group(
modified = modules.highlight.create_component_highlight_group(
new_instance.options.color_modified, 'diff_modified',
new_instance.options),
removed = highlight.create_component_highlight_group(
removed = modules.highlight.create_component_highlight_group(
new_instance.options.color_removed, 'diff_removed',
new_instance.options)
}
@ -109,7 +112,7 @@ Diff.new = function(self, options, child)
if Diff.diff_checker_enabled then
-- setup internal source
utils.define_autocmd('BufWritePost', "lua require'lualine.components.diff'.update_git_diff()")
modules.utils.define_autocmd('BufWritePost', "lua require'lualine.components.diff'.update_git_diff()")
Diff.update_diff_args()
end
@ -136,7 +139,7 @@ Diff.update_status = function(self, is_focused)
if self.options.colored then
-- load the highlights and store them in colors table
for name, highlight_name in pairs(self.highlights) do
colors[name] = highlight.component_format_highlight(highlight_name)
colors[name] = modules.highlight.component_format_highlight(highlight_name)
end
end
@ -242,7 +245,7 @@ function Diff.update_git_diff()
if Diff.diff_args then
Diff.diff_output_cache = {}
if Diff.diff_job then Diff.diff_job:stop() end
Diff.diff_job = Job(Diff.diff_args)
Diff.diff_job = modules.Job(Diff.diff_args)
if Diff.diff_job then Diff.diff_job:start() end
end
end

View File

@ -1,9 +1,11 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local highlight = require('lualine.highlight')
local utils = require('lualine.utils.utils')
local FileType = require('lualine.component'):new()
local lualine_require = require'lualine_require'
local modules = lualine_require.lazy_require{
highlight = 'lualine.highlight',
utils = 'lualine.utils.utils',
}
local FileType = lualine_require.require('lualine.component'):new()
function FileType:new(options, child)
local new_instance = self._parent:new(options, child or FileType)
@ -28,21 +30,21 @@ function FileType:apply_icon()
icon, icon_highlight_group = devicons.get_icon(f_name, f_extension)
if icon and self.options.colored then
local highlight_color = utils.extract_highlight_colors(
local highlight_color = modules.utils.extract_highlight_colors(
icon_highlight_group, 'fg')
local is_focused = utils.is_focused()
local default_highlight = highlight.format_highlight(is_focused,
local is_focused = modules.utils.is_focused()
local default_highlight = modules.highlight.format_highlight(is_focused,
self.options.self
.section)
local icon_highlight = self.options.self.section .. '_' ..
icon_highlight_group
if not utils.highlight_exists(icon_highlight .. '_normal') then
icon_highlight = highlight.create_component_highlight_group(
if not modules.utils.highlight_exists(icon_highlight .. '_normal') then
icon_highlight = modules.highlight.create_component_highlight_group(
{fg = highlight_color}, icon_highlight_group,
self.options)
end
icon = highlight.component_format_highlight(icon_highlight) .. icon ..
icon = modules.highlight.component_format_highlight(icon_highlight) .. icon ..
default_highlight
end
else

View File

@ -1,5 +1,6 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local require = require'lualine_require'.require
local Mode = require('lualine.component'):new()
local get_mode = require('lualine.utils.mode').get_mode

View File

@ -1,22 +1,25 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local M = {}
local cterm_colors
local utils = require 'lualine.utils.utils'
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.cterm_colors',
}
local section_highlight_map = {x = 'c', y = 'b', z = 'a'}
local active_theme = nil
local create_cterm_colors = false
local function sanitize_color(color)
if type(color) == 'string' then
if color:sub(1,1) == '#' then return color end -- RGB value
local converter = require 'lualine.utils.cterm_colors'
return converter.color_name2rgb(color)
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
local converter = require 'lualine.utils.cterm_colors'
return converter.cterm2rgb(color)
return modules.color_utils.cterm2rgb(color)
end
end
@ -30,16 +33,16 @@ function M.highlight(name, foreground, background, gui, link, reload)
table.insert(command, name)
if foreground and foreground ~= 'none' then
table.insert(command, 'guifg=' .. foreground)
if cterm_colors then
if create_cterm_colors then
table.insert(command,
'ctermfg=' .. cterm_colors.get_cterm_color(foreground))
'ctermfg=' .. modules.color_utils.get_cterm_color(foreground))
end
end
if background and background ~= 'none' then
table.insert(command, 'guibg=' .. background)
if cterm_colors then
if create_cterm_colors then
table.insert(command,
'ctermbg=' .. cterm_colors.get_cterm_color(background))
'ctermbg=' .. modules.color_utils.get_cterm_color(background))
end
end
if gui then
@ -49,15 +52,15 @@ function M.highlight(name, foreground, background, gui, link, reload)
end
vim.cmd(table.concat(command, ' '))
if not reload then
utils.save_highlight(name, {name, foreground, background, gui, link, true})
modules.utils.save_highlight(name, {name, foreground, background, gui, link, true})
end
end
function M.create_highlight_groups(theme)
utils.clear_highlights()
modules.utils.clear_highlights()
active_theme = theme
if not vim.opt.termguicolors:get() then
cterm_colors = require 'lualine.utils.cterm_colors'
if not vim.go.termguicolors then
create_cterm_colors = true
end
for mode, sections in pairs(theme) do
for section, color in pairs(sections) do
@ -109,13 +112,13 @@ local function get_default_component_color(color, options_color, default_color,
if type(options_color) == 'table' and options_color[kind] then
return options_color[kind]
elseif type(options_color) == 'string' then
return utils.extract_highlight_colors(options_color, kind)
return modules.utils.extract_highlight_colors(options_color, kind)
end
end
if type(default_color) == 'table' then
return default_color[kind]
elseif type(default_color) == 'string' then
return utils.extract_highlight_colors(default_color, kind)
return modules.utils.extract_highlight_colors(default_color, kind)
end
end
@ -130,9 +133,9 @@ end
-- to retrive highlight group
function M.create_component_highlight_group(color, highlight_tag, options)
local tag_id = 0
while (utils.highlight_exists(table.concat(
while (modules.utils.highlight_exists(table.concat(
{'lualine', highlight_tag, 'no_mode'}, '_'))
or (options.self.section and utils.highlight_exists(table.concat(
or (options.self.section and modules.utils.highlight_exists(table.concat(
{options.self.section, highlight_tag, 'normal'}, '_')))
) do
highlight_tag = highlight_tag .. '_' .. tostring(tag_id)
@ -193,12 +196,12 @@ function M.component_format_highlight(highlight_name)
if highlight_name:find('no_mode') == #highlight_name - #'no_mode' + 1 then
return '%#' .. highlight_group .. '#'
end
if utils.is_focused() then
if modules.utils.is_focused() then
highlight_group = append_mode(highlight_group)
else
highlight_group = highlight_group .. '_inactive'
end
if utils.highlight_exists(highlight_group) then
if modules.utils.highlight_exists(highlight_group) then
return '%#' .. highlight_group .. '#'
else
return '%#' .. highlight_name .. '_normal#'
@ -207,7 +210,7 @@ end
function M.format_highlight(is_focused, highlight_group)
if highlight_group > 'lualine_c'
and not utils.highlight_exists(highlight_group .. '_normal') then
and not modules.utils.highlight_exists(highlight_group .. '_normal') then
highlight_group = 'lualine_' ..
section_highlight_map[highlight_group:match(
'lualine_(.)')]
@ -218,7 +221,7 @@ function M.format_highlight(is_focused, highlight_group)
else
highlight_name = append_mode(highlight_group)
end
if utils.highlight_exists(highlight_name) then
if modules.utils.highlight_exists(highlight_name) then
return '%#' .. highlight_name .. '#'
end
return '%#' .. highlight_group .. '_normal#'
@ -236,11 +239,11 @@ function M.get_transitional_highlights(left_hl, right_hl)
-- construct the name of hightlight group
local highlight_name = table.concat({'lualine_transitional',left_hl,'to',right_hl}, '_')
if not utils.highlight_exists(highlight_name) then
if not modules.utils.highlight_exists(highlight_name) then
-- Create the highlight_group if needed
-- Get colors from highlights
local fg = utils.extract_highlight_colors(left_hl, 'bg')
local bg = utils.extract_highlight_colors(right_hl, 'bg')
local fg = modules.utils.extract_highlight_colors(left_hl, 'bg')
local bg = modules.utils.extract_highlight_colors(right_hl, 'bg')
if not fg or not bg then return nil end -- Color retrieval failed
if bg == fg then return nil end -- Separator won't be visible anyway
M.highlight(highlight_name, fg, bg, nil)

View File

@ -1,6 +1,7 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local modules = require('lualine.utils.lazy_require'){
local lualine_require = require'lualine_require'
local modules = lualine_require.lazy_require{
highlight = 'lualine.highlight',
loader = 'lualine.utils.loader',
utils_section = 'lualine.utils.section',
@ -284,6 +285,7 @@ local function setup(user_config)
new_config = true
config = modules.config_module.apply_configuration(user_config)
vim.go.statusline = "%{%v:lua.require'lualine'.statusline()%}"
vim.go.laststatus = 2
end
return {

View File

@ -1,13 +0,0 @@
return function(modules)
return setmetatable({}, {
__index = function(self, key)
local loaded = rawget(self, key)
if loaded ~= nil then return loaded end
local module_location = modules[key]
if module_location == nil then return nil end
local module = require(module_location)
rawset(self, key, module)
return module
end
})
end

View File

@ -1,73 +1,20 @@
-- Copyright (c) 2020-2021 hoob3rt
-- MIT license, see LICENSE for more details.
local lualine_require = require'lualine_require'
local require = lualine_require.require
local notice = require'lualine.utils.notices'
local utils = require'lualine.utils.utils'
local is_valid_filename = lualine_require.is_valid_filename
local function lualine_load(patern, use_cache)
assert(utils.is_valid_filename(patern[#patern]), "Invalid filename")
local retval, cache_name = nil, nil
local sep = package.config:sub(1,1)
if use_cache == true then
-- Turn {lua, lualine, module, name} -> lualine.module.name
-- same formst that require uses
-- then check if it's in requires cache
local copy_patern = {}
local start = patern[1] == 'lua' and 2 or 1
local copy_start = 1
for i=start, #patern do
copy_patern[copy_start] = patern[i]
copy_start = copy_start + 1
end
cache_name = table.concat(copy_patern, '.')
if package.loaded[cache_name] then
return package.loaded[cache_name]
end
end
-- Get all the runtime files that match the patern
local files = vim.fn.uniq(vim.api.nvim_get_runtime_file(
table.concat(patern, sep)..'.lua', true))
local n_files = #files
if n_files == 0 then
-- No match found
error(table.concat(patern, sep) .. " 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
-- 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
-- apear to be in lualines repo . Just run the first one
retval = dofile(files[1])
end
end
if use_cache == true and cache_name then
package.loaded[cache_name] = retval
end
return retval
end
local sep = package.config:sub(1,1)
local component_types = {
luaf = function(component)
return
lualine_load({'lua', 'lualine', 'components', 'special', 'function_component'}, true):new(component)
require('lualine.components.special.function_component'):new(component)
end,
mod = function(component)
local ok, loaded_component = pcall(lualine_load,
{'lua', 'lualine', 'components', component[1]}, true)
local ok, loaded_component = pcall(require,'lualine.components.'..component[1])
if ok then
component.component_name = component[1]
loaded_component = loaded_component:new(component)
@ -78,15 +25,15 @@ local component_types = {
local stl_expr = component[1] -- Vim's %p %l statusline elements
component[1] = function() return stl_expr end
return
lualine_load({'lua', 'lualine', 'components', 'special', 'function_component'}, true):new(component)
require('lualine.components.special.function_component'):new(component)
end,
var = function(component)
return
lualine_load({'lua', 'lualine', 'components', 'special', 'vim_var_component'}, true):new(component)
require('lualine.components.special.vim_var_component'):new(component)
end,
['_'] = function(component)
return
lualine_load({'lua', 'lualine', 'components', 'special', 'eval_func_component'}, true):new(component)
require('lualine.components.special.eval_func_component'):new(component)
end
}
@ -146,7 +93,7 @@ local function load_extensions(config)
local loaded_extensions = {}
for _, extension in pairs(config.extensions) do
if type(extension) == 'string' then
local ok, local_extension = pcall(lualine_load, {'lua', 'lualine', 'extensions', extension}, true)
local ok, local_extension = pcall(require, 'lualine.extensions.' ..extension)
if ok then
local_extension = vim.deepcopy(local_extension)
load_sections(local_extension.sections, config.options)
@ -184,7 +131,36 @@ local function load_all(config)
end
local function load_theme(theme_name)
return lualine_load({'lua', 'lualine', 'themes', theme_name}, false)
assert(is_valid_filename(theme_name), "Invalid filename")
local retval
local path = table.concat({'lua', 'lualine', 'themes', theme_name}, sep)..'.lua'
local files = vim.fn.globpath(vim.api.nvim_get_option('rtp'),
path, true, true)
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
-- 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
-- apear to be in lualines repo . Just run the first one
retval = dofile(files[1])
end
end
return retval
end
return {

View File

@ -75,11 +75,6 @@ function M.is_focused()
return tonumber(vim.g.actual_curwin) == vim.fn.win_getid()
end
function M.is_valid_filename(name)
local invalid_chars="[^a-zA-Z0-9_. -]"
return name:find(invalid_chars) == nil
end
function M.charAt(str, pos)
return string.char(str:byte(pos))
end

47
lua/lualine_require.lua Normal file
View File

@ -0,0 +1,47 @@
local M = {}
M.sep = package.config:sub(1,1)
local source = debug.getinfo(1, "S").source
if source:sub(1,1) == '@' then
local base_start = source:find(table.concat({'lualine.nvim', 'lua', 'lualine_require.lua'}, M.sep))
if base_start then
source = source:sub(2, base_start + 12 + 1 + 3) -- #lualine.nvim = 12 , #lua = 3.
if source then M.plugin_dir = source end
end
end
function M.is_valid_filename(name)
local invalid_chars="[^a-zA-Z0-9_. -]"
return name:find(invalid_chars) == nil
end
function M.require(module)
if package.loaded[module] then return package.loaded[module] end
if M.plugin_dir then
local path = M.plugin_dir .. module:gsub('%.', M.sep) .. '.lua'
assert(M.is_valid_filename(module), "Invalid filename")
if vim.loop.fs_stat(path) then
local mod_result = dofile(path)
package.loaded[module] = mod_result
return mod_result
end
end
return require(module)
end
function M.lazy_require(modules)
return setmetatable({}, {
__index = function(self, key)
local loaded = rawget(self, key)
if loaded ~= nil then return loaded end
local module_location = modules[key]
if module_location == nil then return nil end
local module = M.require(module_location)
rawset(self, key, module)
return module
end
})
end
return M