From fac96d71cca25b4c4fb286caee024bc1e8246a25 Mon Sep 17 00:00:00 2001 From: shadmansaleh <13149513+shadmansaleh@users.noreply.github.com> Date: Sun, 8 Aug 2021 22:03:58 +0600 Subject: [PATCH] [Breaking] Refactor: switch to %{%expr%} from %!expr Huge change to internal mechanics. - Now %{%expr%} blocks are used for evaluating statusline instead of %!expr . Pros for this is statusline is evaluated on current win and buf context instead of active win & bufs context. - Now all components branch & diff(These two are cached) including users function components updates on inactive status. - now components update status and function components receive an argument (is_focused) when called. It indicates whether it's running for active or inactive statusline. - Now lualine no longer aggrasively takes over 'statusline' option. instead it sets the global version of statusline option. So it's possible to unset it to hide lualine . Or set buffer local version of that option to have different statusline then lualine on thay buffer - Switch vim.o to vim.go or vim.opt. - BugFix autcommands being set everytime an instence of diff or branch component is created - Added new utils functions define_autocmd & is_focused - Remove utils function lualine_eval - Removed hacky require cache modification from component.lua --- lua/lualine/component.lua | 28 +++---------------- lua/lualine/components/branch.lua | 12 +++++--- lua/lualine/components/diff.lua | 23 ++++++++------- lua/lualine/components/filename.lua | 2 -- lua/lualine/components/filetype.lua | 2 +- .../components/special/function_component.lua | 4 +-- lua/lualine/highlight.lua | 4 +-- lua/lualine/init.lua | 20 ++++++------- lua/lualine/themes/papercolor.lua | 2 +- lua/lualine/themes/solarized.lua | 2 +- lua/lualine/utils/section.lua | 3 +- lua/lualine/utils/utils.lua | 23 ++++++++++----- 12 files changed, 58 insertions(+), 67 deletions(-) diff --git a/lua/lualine/component.lua b/lua/lualine/component.lua index 05020ce..88333ef 100644 --- a/lua/lualine/component.lua +++ b/lua/lualine/component.lua @@ -5,14 +5,6 @@ local highlight = require 'lualine.highlight' -- Used to provide a unique id for each component local component_no = 1 --- Here we're manupulation the require() cache so when we --- require('lualine.component.components') it will return this table --- It's hacky but package.loaded is documented in lua docs so from --- standereds point of view we're good ]. I think it's better than --- modifiying global state -package.loaded['lualine.component.components'] = {} -local components = package.loaded['lualine.component.components'] - local Component = { -- Creates a new component new = function(self, options, child) @@ -27,7 +19,6 @@ local Component = { new_component.options.component_name = tostring(component_no) end new_component.component_no = component_no - components[component_no] = new_component new_component:set_separator() new_component:create_option_highlights() end @@ -157,22 +148,13 @@ local Component = { -- luacheck: pop -- Driver code of the class - draw = function(self, default_highlight, statusline_inactive) - -- Check if we are in in inactive state and need to enable inactive_eval - -- for this compoennt - if self.inactive_eval and not statusline_inactive and vim.g.statusline_winid ~= - vim.fn.win_getid() then - -- In that case we'll return a evaluator - self.status = '%' .. string.format( - '{%%v:lua.require\'lualine.utils.utils\'.lualine_eval(%s,\'\',v:true)%%}', - tostring(self.component_no)) - return self.status - end + draw = function(self, default_highlight, is_focused) self.status = '' + if self.options.condition ~= nil and self.options.condition() ~= true then return self.status end - local status = self:update_status() + local status = self:update_status(is_focused) if self.options.format then status = self.options.format(status or '') end if type(status) == 'string' and #status > 0 then self.status = status @@ -181,9 +163,7 @@ local Component = { self:apply_padding() self:apply_section_separators() self:apply_highlights(default_highlight) - if not (statusline_inactive and self.last_component) then - self:apply_separator() - end + self:apply_separator() end return self.status end diff --git a/lua/lualine/components/branch.lua b/lua/lualine/components/branch.lua index 0773334..81374c4 100644 --- a/lua/lualine/components/branch.lua +++ b/lua/lualine/components/branch.lua @@ -1,14 +1,14 @@ -- Copyright (c) 2020-2021 shadmansaleh -- MIT license, see LICENSE for more details. +local utils = require('lualine.utils.utils') local Branch = require('lualine.component'):new() - -- vars Branch.git_branch = '' -- os specific path separator Branch.sep = package.config:sub(1, 1) -- event watcher to watch head file Branch.file_changed = vim.loop.new_fs_event() - +local branch_cache = {} -- stores last known branch for a buffer -- Initilizer Branch.new = function(self, options, child) local new_branch = self._parent:new(options, child or Branch) @@ -18,11 +18,14 @@ Branch.new = function(self, options, child) -- run watch head on load so branch is present when component is loaded Branch.update_branch() -- update branch state of BufEnter as different Buffer may be on different repos - vim.cmd [[autocmd lualine BufEnter * lua require'lualine.components.branch'.update_branch()]] + utils.define_autocmd('BufEnter', "lua require'lualine.components.branch'.update_branch()") return new_branch end -Branch.update_status = function() return Branch.git_branch end +Branch.update_status = function(_, is_focused) + if not is_focused then return branch_cache[vim.fn.bufnr()] or '' end + return Branch.git_branch +end -- returns full path to git directory for current directory function Branch.find_git_dir() @@ -90,6 +93,7 @@ function Branch.update_branch() -- set to '' when git dir was not found Branch.git_branch = '' end + branch_cache[vim.fn.bufnr()] = Branch.git_branch end return Branch diff --git a/lua/lualine/components/diff.lua b/lua/lualine/components/diff.lua index bba4adf..1a18459 100644 --- a/lua/lualine/components/diff.lua +++ b/lua/lualine/components/diff.lua @@ -20,6 +20,8 @@ Diff.default_colors = { modified = '#ff0038' } +local diff_cache = {} -- Stores last known value of diff of a buffer + -- Initializer Diff.new = function(self, options, child) local new_instance = self._parent:new(options, child or Diff) @@ -64,22 +66,22 @@ Diff.new = function(self, options, child) if type(new_instance.options.source) ~= 'function' then -- setup internal source - vim.cmd [[ - autocmd lualine BufEnter * lua require'lualine.components.diff'.update_diff_args() - autocmd lualine BufWritePost * lua require'lualine.components.diff'.update_git_diff() - ]] + utils.define_autocmd('BufEnter', "lua require'lualine.components.diff'.update_diff_args()") + utils.define_autocmd('BufWritePost', "lua require'lualine.components.diff'.update_git_diff()") end return new_instance end -- Function that runs everytime statusline is updated -Diff.update_status = function(self) +Diff.update_status = function(self, is_focused) + local git_diff = Diff.git_diff if self.options.source then - Diff.git_diff = self.options.source() + git_diff = self.options.source() end - if Diff.git_diff == nil then return '' end + if not is_focused then git_diff = diff_cache[vim.fn.bufnr()] or {} end + if git_diff == nil then return '' end local colors = {} if self.options.colored then @@ -92,12 +94,12 @@ Diff.update_status = function(self) local result = {} -- loop though data and load available sections in result table for _, name in ipairs {'added', 'modified', 'removed'} do - if Diff.git_diff[name] and Diff.git_diff[name] > 0 then + if git_diff[name] and git_diff[name] > 0 then if self.options.colored then table.insert(result, colors[name] .. self.options.symbols[name] .. - Diff.git_diff[name]) + git_diff[name]) else - table.insert(result, self.options.symbols[name] .. Diff.git_diff[name]) + table.insert(result, self.options.symbols[name] .. git_diff[name]) end end end @@ -180,6 +182,7 @@ function Diff.update_diff_args() else Diff.git_diff = {added = 0, modified = 0, removed = 0} end + diff_cache[vim.fn.bufnr()] = Diff.git_diff end } Diff.update_git_diff() diff --git a/lua/lualine/components/filename.lua b/lua/lualine/components/filename.lua index 1230934..d43c60b 100644 --- a/lua/lualine/components/filename.lua +++ b/lua/lualine/components/filename.lua @@ -2,8 +2,6 @@ -- MIT license, see LICENSE for more details. local FileName = require('lualine.component'):new() -FileName.inactive_eval = true - local function count(base, pattern) return select(2, string.gsub(base, pattern, '')) end diff --git a/lua/lualine/components/filetype.lua b/lua/lualine/components/filetype.lua index 4536933..57cd13e 100644 --- a/lua/lualine/components/filetype.lua +++ b/lua/lualine/components/filetype.lua @@ -30,7 +30,7 @@ function FileType:apply_icon() if icon and self.options.colored then local highlight_color = utils.extract_highlight_colors( icon_highlight_group, 'fg') - local is_focused = vim.g.statusline_winid == vim.fn.win_getid() + local is_focused = utils.is_focused() local default_highlight = highlight.format_highlight(is_focused, self.options.self .section) diff --git a/lua/lualine/components/special/function_component.lua b/lua/lualine/components/special/function_component.lua index e18f26f..132bd27 100644 --- a/lua/lualine/components/special/function_component.lua +++ b/lua/lualine/components/special/function_component.lua @@ -1,8 +1,8 @@ local FunctionComponent = require('lualine.component'):new() -FunctionComponent.update_status = function(self) +FunctionComponent.update_status = function(self, is_focused) -- 1st element in options table is the function provided by config - return self.options[1]() + return self.options[1](is_focused) end return FunctionComponent diff --git a/lua/lualine/highlight.lua b/lua/lualine/highlight.lua index 7334a67..c39f69e 100644 --- a/lua/lualine/highlight.lua +++ b/lua/lualine/highlight.lua @@ -51,7 +51,7 @@ end function M.create_highlight_groups(theme) utils.clear_highlights() active_theme = theme - if not vim.o.termguicolors then + if not vim.opt.termguicolors:get() then cterm_colors = require 'lualine.utils.cterm_colors' end for mode, sections in pairs(theme) do @@ -154,7 +154,7 @@ function M.component_format_highlight(highlight_name) if highlight_name:find('no_mode') == #highlight_name - #'no_mode' + 1 then return '%#' .. highlight_group .. '#' end - if vim.g.statusline_winid == vim.fn.win_getid() then + if utils.is_focused() then highlight_group = append_mode(highlight_group) else highlight_group = highlight_group .. '_inactive' diff --git a/lua/lualine/init.lua b/lua/lualine/init.lua index 3937fb6..773482c 100644 --- a/lua/lualine/init.lua +++ b/lua/lualine/init.lua @@ -3,6 +3,7 @@ local highlight = require('lualine.highlight') local loader = require('lualine.utils.loader') local utils_section = require('lualine.utils.section') +local utils = require('lualine.utils.utils') local config_module = require('lualine.config') local config = config_module.config @@ -145,9 +146,8 @@ end local function status_dispatch() -- disable on specific filetypes - local current_ft = vim.api.nvim_buf_get_option( - vim.fn.winbufnr(vim.g.statusline_winid), 'filetype') - local is_focused = vim.g.statusline_winid == vim.fn.win_getid() + local current_ft = vim.bo.filetype + local is_focused = utils.is_focused() for _, ft in pairs(config.options.disabled_filetypes) do if ft == current_ft then vim.wo.statusline = '' @@ -190,24 +190,22 @@ local function setup_theme() vim.cmd [[ autocmd lualine ColorScheme * lua require'lualine.utils.utils'.reload_highlights() autocmd lualine OptionSet background lua require'lualine'.setup() - ]] + ]] end local function set_tabline() if next(config.tabline) ~= nil then - vim.o.tabline = '%!v:lua.require\'lualine\'.tabline()' - vim.o.showtabline = 2 + vim.go.tabline = "%{%v:lua.require'lualine'.tabline()%}" + vim.go.showtabline = 2 end end local function set_statusline() if next(config.sections) ~= nil or next(config.inactive_sections) ~= nil then - vim.o.statusline = '%!v:lua.require\'lualine\'.statusline()' - vim.api.nvim_exec([[ - autocmd lualine WinLeave,BufLeave * lua vim.wo.statusline=require'lualine'.statusline() - autocmd lualine BufWinEnter,WinEnter,BufEnter,SessionLoadPost * set statusline< + vim.go.statusline = "%{%v:lua.require'lualine'.statusline()%}" + vim.cmd([[ autocmd lualine VimResized * redrawstatus - ]], false) + ]]) end end diff --git a/lua/lualine/themes/papercolor.lua b/lua/lualine/themes/papercolor.lua index 15abb8c..ea3c9bb 100644 --- a/lua/lualine/themes/papercolor.lua +++ b/lua/lualine/themes/papercolor.lua @@ -1,6 +1,6 @@ -- Copyright (c) 2020-2021 shadmansaleh -- MIT license, see LICENSE for more details. -- Credit: itchyny(lightline) -local background = vim.o.background +local background = vim.opt.background:get() return require('lualine.themes.papercolor_' .. background) diff --git a/lua/lualine/themes/solarized.lua b/lua/lualine/themes/solarized.lua index a8b544f..2e72cf9 100644 --- a/lua/lualine/themes/solarized.lua +++ b/lua/lualine/themes/solarized.lua @@ -2,6 +2,6 @@ -- MIT license, see LICENSE for more details. -- Credit: itchyny(lightline) -- License: MIT License -local background = vim.o.background +local background = vim.opt.background:get() return require('lualine.themes.solarized_' .. background) diff --git a/lua/lualine/utils/section.lua b/lua/lualine/utils/section.lua index 5bfb04f..e508521 100644 --- a/lua/lualine/utils/section.lua +++ b/lua/lualine/utils/section.lua @@ -15,7 +15,7 @@ function M.draw_section(section, section_name, is_focused) (type(component) == 'table' and not component.component_no) then return '' -- unknown element in section. section posibly not yet loaded end - table.insert(status, component:draw(highlight_name)) + table.insert(status, component:draw(highlight_name, is_focused)) end -- Flags required for knowing when to remove component separator @@ -38,7 +38,6 @@ function M.draw_section(section, section_name, is_focused) .options.section_separators[1]) end end - section[component_no].last_component = true end -- Remove component separator when color option is used in next component if strip_next_component then diff --git a/lua/lualine/utils/utils.lua b/lua/lualine/utils/utils.lua index 59da208..706c326 100644 --- a/lua/lualine/utils/utils.lua +++ b/lua/lualine/utils/utils.lua @@ -56,14 +56,23 @@ function M.list_shrink(list) return new_list end --- Wvaluate a component -function M.lualine_eval(id, ...) - local ok, components = pcall(require, 'lualine.component.components') - if ok and components then - return components[id]:draw(...) - else - return '' +-- Check if a auto command is already defined +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 +end + +-- Define a auto command if it's not already defined +function M.define_autocmd(event, patern, cmd) + if not cmd then cmd = patern; patern = '*' end + if not autocmd_is_defined(event, patern, cmd) then + vim.cmd(string.format("autocmd lualine %s %s %s", event, patern, cmd)) end end +-- Check if statusline is on focused window or not +function M.is_focused() + return tonumber(vim.g.actual_curwin) == vim.fn.win_getid() +end + return M