[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
This commit is contained in:
shadmansaleh 2021-08-08 22:03:58 +06:00
parent cb5c4c031e
commit fac96d71cc
12 changed files with 58 additions and 67 deletions

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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