diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md index e512526..f9e552a 100644 --- a/BREAKING_CHANGES.md +++ b/BREAKING_CHANGES.md @@ -61,3 +61,33 @@ See [#24](https://github.com/shadmansaleh/lualine.nvim/pull/24) for details modified, removed in diff_color table option - color_error, color_warning, color_info, color_hint are now available as error, warn, info, hint in diagnostics_color table option + +### Component class refactor +***Applicable only ones responsible for custom components*** +- Now call extend method on super class to create new type of component instead of calling new with empty args. +- Don't overrite new method for initialization. Overrite init instead. +- rename Component._parent -> Component.super +- Call methods from super class directly on classes super not through + objects super or self.super +So basically if you had something like +```lua +local my_comp = require'lualine.component':new() +function mycomp:new(options, child) + local obj = self._parent:new(options, child or my_comp) + obj.x = 1 + obj.y = 2 + return obj +end +``` +change it to +```lua +local my_comp = require('lualine.component'):extend() + +function my_comp:init(options) + -- Notice carefully it's not self.super.init nor my_comp.super:init + my_comp.super.init(self, options) + self.x = 1 + self.y = 2 +end +``` + diff --git a/README.md b/README.md index 880bd3e..56dbb15 100644 --- a/README.md +++ b/README.md @@ -390,8 +390,8 @@ sections = { -- When type is omitted lualine will guess it. -- Available types [format: type_name(example)] -- mod(branch/filename), stl(%f/%m), var(g:coc_status/bo:modifiable), - -- luae(lua expressions), vimf(viml function name) - -- luae is short for lua-expression and vimf is short fror vim-function + -- lua_expr(lua expressions), vim_fun(viml function name) + -- lua_expr is short for lua-expression and vim_fun is short fror vim-function type = nil, padding = 1, -- adds padding to the left and right of components -- padding can be specified to left or right separately like diff --git a/doc/lualine.txt b/doc/lualine.txt index 63cd840..33e0d00 100644 --- a/doc/lualine.txt +++ b/doc/lualine.txt @@ -371,8 +371,8 @@ for all components. -- When type is omitted lualine will guess it. -- Available types [format: type_name(example)] -- mod(branch/filename), stl(%f/%m), var(g:coc_status/bo:modifiable), - -- luae(lua expressions), vimf(viml function name) - -- luae is short for lua-expression and vimf is short fror vim-function + -- lua_expr(lua expressions), vim_fun(viml function name) + -- lua_expr is short for lua-expression and vim_fun is short fror vim-function type = nil, padding = 1, -- adds padding to the left and right of components -- padding can be specified to left or right separately like diff --git a/lua/lualine/component.lua b/lua/lualine/component.lua index 5fd2282..f461501 100644 --- a/lua/lualine/component.lua +++ b/lua/lualine/component.lua @@ -1,216 +1,180 @@ -- Copyright (c) 2020-2021 shadmansaleh -- MIT license, see LICENSE for more details. +local require = require('lualine_require').require local highlight = require 'lualine.highlight' +local M = require('lualine.utils.class'):extend() -- Used to provide a unique id for each component local component_no = 1 -local function check_deprecated_options(options) - local function rename_notice(before, now) - if options[before] then - require('lualine.utils.notices').add_notice(string.format( - [[ -### option.%s -%s option has been renamed to `%s`. Please use `%s` instead in your config -for %s component. -]], - before, - before, - now, - now, - options.component_name or 'function' - )) - options[now] = options[before] - options[before] = nil +function M:__tostring() + local str = 'Component: ' .. self.options.component_name + if self.debug then + str = str .. '\n---------------------\n' .. vim.inspect(self) + end + return str +end + +-- Initialize new component +function M:init(options) + self.options = options or {} + component_no = component_no + 1 + if not options.component_name then + self.options.component_name = tostring(component_no) + end + self.component_no = component_no + self:set_separator() + self:create_option_highlights() +end + +function M:set_separator() + if self.options.separator == nil then + if self.options.component_separators then + if self.options.self.section < 'lualine_x' then + self.options.separator = self.options.component_separators.left + else + self.options.separator = self.options.component_separators.right + end end end - rename_notice('format', 'fmt') - rename_notice('condition', 'cond') end -local Component = { - -- Creates a new component - new = function(self, options, child) - local new_component = {} - new_component.options = options - new_component._parent = child or self - setmetatable(new_component, { __index = new_component._parent }) - -- Operation that are required for creating new components but not for inheritence - if options ~= nil then - component_no = component_no + 1 - check_deprecated_options(new_component.options) - if not options.component_name then - new_component.options.component_name = tostring(component_no) + +function M:create_option_highlights() + -- set custom highlights + if self.options.color then + self.options.color_highlight = highlight.create_component_highlight_group( + self.options.color, + self.options.component_name, + self.options + ) + end +end + +-- Adds spaces to left and right of a component +function M:apply_padding() + local padding = self.options.padding + local l_padding, r_padding + if padding == nil then + padding = 1 + end + if type(padding) == 'number' then + l_padding, r_padding = padding, padding + elseif type(padding) == 'table' then + l_padding, r_padding = padding.left, padding.right + end + if l_padding then + if self.status:find '%%#.*#' == 1 then + -- When component has changed the highlight at begining + -- we will add the padding after the highlight + local pre_highlight = vim.fn.matchlist(self.status, [[\(%#.\{-\}#\)]])[2] + self.status = pre_highlight .. string.rep(' ', l_padding) .. self.status:sub(#pre_highlight + 1, #self.status) + else + self.status = string.rep(' ', l_padding) .. self.status + end + end + if r_padding then + self.status = self.status .. string.rep(' ', r_padding) + end +end + +-- Applies custom highlights for component +function M:apply_highlights(default_highlight) + if self.options.color_highlight then + self.status = highlight.component_format_highlight(self.options.color_highlight) .. self.status + end + if type(self.options.separator) ~= 'table' and self.status:find '%%#' then + -- Apply default highlight only when we aren't applying trans sep and + -- the component has changed it's hl. since we won't be applying + -- regular sep in those cases so ending with default hl isn't neccessay + self.status = self.status .. default_highlight + -- Also put it in applied sep so when sep get struped so does the hl + self.applied_separator = default_highlight + end + -- Prepend default hl when the component doesn't start with hl otherwise + -- color in previous component can cause side effect + if not self.status:find '^%%#' then + self.status = default_highlight .. self.status + end +end + +-- Apply icon in front of component +function M:apply_icon() + if self.options.icons_enabled and self.options.icon then + self.status = self.options.icon .. ' ' .. self.status + end +end + +-- Apply separator at end of component only when +-- custom highlights haven't affected background +function M:apply_separator() + local separator = self.options.separator + if type(separator) == 'table' then + if self.options.separator[2] == '' then + if self.options.self.section < 'lualine_x' then + separator = self.options.component_separators.left + else + separator = self.options.component_separators.right end - new_component.component_no = component_no - new_component:set_separator() - new_component:create_option_highlights() - end - return new_component - end, - - set_separator = function(self) - if self.options.separator == nil then - if self.options.component_separators then - if self.options.self.section < 'lualine_x' then - self.options.separator = self.options.component_separators.left - else - self.options.separator = self.options.component_separators.right - end - end - end - end, - - create_option_highlights = function(self) - -- set custom highlights - if self.options.color then - self.options.color_highlight = highlight.create_component_highlight_group( - self.options.color, - self.options.component_name, - self.options - ) - end - end, - - -- set upper or lower case - apply_case = function(self) - -- Donn't work on components that emit vim statusline escaped chars - if self.status:find '%%' and not self.status:find '%%%%' then + else return end - if self.options.upper == true then - self.status = self.status:upper() - elseif self.options.lower == true then - self.status = self.status:lower() - end - end, + end + if separator and #separator > 0 then + self.status = self.status .. separator + self.applied_separator = self.applied_separator .. separator + end +end - -- Adds spaces to left and right of a component - apply_padding = function(self) - local padding = self.options.padding - local l_padding, r_padding - if padding == nil then - padding = 1 - end - if type(padding) == 'number' then - l_padding, r_padding = padding, padding - elseif type(padding) == 'table' then - l_padding, r_padding = padding.left, padding.right - end - if l_padding then - if self.status:find '%%#.*#' == 1 then - -- When component has changed the highlight at begining - -- we will add the padding after the highlight - local pre_highlight = vim.fn.matchlist(self.status, [[\(%#.\{-\}#\)]])[2] - self.status = pre_highlight .. string.rep(' ', l_padding) .. self.status:sub(#pre_highlight + 1, #self.status) - else - self.status = string.rep(' ', l_padding) .. self.status - end - end - if r_padding then - self.status = self.status .. string.rep(' ', r_padding) - end - end, +function M:apply_section_separators() + if type(self.options.separator) ~= 'table' then + return + end + if self.options.separator.left ~= nil and self.options.separator.left ~= '' then + self.status = string.format('%%s{%s}%s', self.options.separator.left, self.status) + self.strip_previous_separator = true + end + if self.options.separator.right ~= nil and self.options.separator.right ~= '' then + self.status = string.format('%s%%S{%s}', self.status, self.options.separator.right) + end +end - -- Applies custom highlights for component - apply_highlights = function(self, default_highlight) - if self.options.color_highlight then - self.status = highlight.component_format_highlight(self.options.color_highlight) .. self.status - end - if type(self.options.separator) ~= 'table' and self.status:find '%%#' then - -- Apply default highlight only when we aren't applying trans sep and - -- the component has changed it's hl. since we won't be applying - -- regular sep in those cases so ending with default hl isn't neccessay - self.status = self.status .. default_highlight - -- Also put it in applied sep so when sep get struped so does the hl - self.applied_separator = default_highlight - end - -- Prepend default hl when the component doesn't start with hl otherwise - -- color in previous component can cause side effect - if not self.status:find '^%%#' then - self.status = default_highlight .. self.status - end - end, - - -- Apply icon in front of component - apply_icon = function(self) - if self.options.icons_enabled and self.options.icon then - self.status = self.options.icon .. ' ' .. self.status - end - end, - - -- Apply separator at end of component only when - -- custom highlights haven't affected background - apply_separator = function(self) - local separator = self.options.separator - if type(separator) == 'table' then - if self.options.separator[2] == '' then - if self.options.self.section < 'lualine_x' then - separator = self.options.component_separators.left - else - separator = self.options.component_separators.right - end - else - return - end - end - if separator and #separator > 0 then - self.status = self.status .. separator - self.applied_separator = self.applied_separator .. separator - end - end, - - apply_section_separators = function(self) - if type(self.options.separator) ~= 'table' then - return - end - if self.options.separator.left ~= nil and self.options.separator.left ~= '' then - self.status = string.format('%%s{%s}%s', self.options.separator.left, self.status) - self.strip_previous_separator = true - end - if self.options.separator.right ~= nil and self.options.separator.right ~= '' then - self.status = string.format('%s%%S{%s}', self.status, self.options.separator.right) - end - end, - - strip_separator = function(self) - if not self.applied_separator then - self.applied_separator = '' - end - self.status = self.status:sub(1, (#self.status - #self.applied_separator)) - self.applied_separator = nil - return self.status - end, - - -- variable to store component output for manipulation - status = '', - -- Actual function that updates a component. Must be overwritten with component functionality - -- luacheck: push no unused args - update_status = function(self, is_focused) end, - -- luacheck: pop - - -- Driver code of the class - draw = function(self, default_highlight, is_focused) - self.status = '' +function M:strip_separator() + if not self.applied_separator then self.applied_separator = '' + end + self.status = self.status:sub(1, (#self.status - #self.applied_separator)) + self.applied_separator = nil + return self.status +end - if self.options.cond ~= nil and self.options.cond() ~= true then - return self.status - end - local status = self:update_status(is_focused) - if self.options.fmt then - status = self.options.fmt(status or '') - end - if type(status) == 'string' and #status > 0 then - self.status = status - self:apply_icon() - self:apply_case() - self:apply_padding() - self:apply_highlights(default_highlight) - self:apply_section_separators() - self:apply_separator() - 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 +function M:update_status(is_focused) end +-- luacheck: pop + +-- Driver code of the class +function M:draw(default_highlight, is_focused) + self.status = '' + self.applied_separator = '' + + if self.options.cond ~= nil and self.options.cond() ~= true then return self.status - end, -} + end + local status = self:update_status(is_focused) + if self.options.fmt then + status = self.options.fmt(status or '') + end + if type(status) == 'string' and #status > 0 then + self.status = status + self:apply_icon() + self:apply_padding() + self:apply_highlights(default_highlight) + self:apply_section_separators() + self:apply_separator() + end + return self.status +end -return Component +return M diff --git a/lua/lualine/components/branch.lua b/lua/lualine/components/branch/git_branch.lua similarity index 51% rename from lua/lualine/components/branch.lua rename to lua/lualine/components/branch/git_branch.lua index 87832e5..75831ba 100644 --- a/lua/lualine/components/branch.lua +++ b/lua/lualine/components/branch/git_branch.lua @@ -1,51 +1,64 @@ --- Copyright (c) 2020-2021 shadmansaleh --- MIT license, see LICENSE for more details. -local Branch = require('lualine.component'):new() -local modules = require('lualine_require').lazy_require { - utils = 'lualine.utils.utils', -} +local M = {} + +local require = require('lualine_require').require +local utils = require 'lualine.utils.utils' + -- vars -Branch.git_branch = '' -Branch.git_dir = '' +local current_git_branch = '' +local current_git_dir = '' +local branch_cache = {} -- stores last known branch for a buffer +local active_bufnr = '0' -- os specific path separator -Branch.sep = package.config:sub(1, 1) +local sep = package.config:sub(1, 1) -- event watcher to watch head file -- Use file wstch for non windows and poll for windows. -- windows doesn't like file watch for some reason. -Branch.file_changed = Branch.sep ~= '\\' and vim.loop.new_fs_event() or vim.loop.new_fs_poll() -Branch.active_bufnr = '0' -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) - if not new_branch.options.icon then - new_branch.options.icon = '' -- e0a0 - end - -- run watch head on load so branch is present when component is loaded - Branch.find_git_dir() - -- update branch state of BufEnter as different Buffer may be on different repos - modules.utils.define_autocmd('BufEnter', "lua require'lualine.components.branch'.find_git_dir()") - return new_branch -end - -Branch.update_status = function(_, is_focused) - if Branch.active_bufnr ~= vim.g.actual_curbuf then - -- Workaround for https://github.com/hoob3rt/lualine.nvim/issues/286 - -- See upstream issue https://github.com/neovim/neovim/issues/15300 - -- Diff is out of sync re sync it. - Branch.find_git_dir() - end - if not is_focused then - return branch_cache[vim.fn.bufnr()] or '' - end - return Branch.git_branch -end - +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 --- returns full path to git directory for current directory -function Branch.find_git_dir() + +-- sets git_branch veriable to branch name or commit hash if not on branch +local function get_git_head(head_file) + local f_head = io.open(head_file) + if f_head then + local HEAD = f_head:read() + f_head:close() + local branch = HEAD:match 'ref: refs/heads/(.+)$' + if branch then + current_git_branch = branch + else + current_git_branch = HEAD:sub(1, 6) + end + end + return nil +end + +-- Update branch +local function update_branch() + active_bufnr = tostring(vim.fn.bufnr()) + file_changed:stop() + local git_dir = current_git_dir + if git_dir and #git_dir > 0 then + local head_file = git_dir .. sep .. 'HEAD' + get_git_head(head_file) + file_changed:start( + head_file, + sep ~= '\\' and {} or 1000, + vim.schedule_wrap(function() + -- reset file-watch + update_branch() + end) + ) + else + -- set to '' when git dir was not found + current_git_branch = '' + end + branch_cache[vim.fn.bufnr()] = current_git_branch +end + +-- returns full path to git directory for dir_path or current directory +function M.find_git_dir(dir_path) -- get file dir so we can search from that dir - local file_dir = vim.fn.expand '%:p:h' + local file_dir = dir_path or vim.fn.expand '%:p:h' local root_dir = file_dir local git_dir -- Search upward for .git file or folder @@ -54,7 +67,7 @@ function Branch.find_git_dir() git_dir = git_dir_cache[root_dir] break end - local git_path = root_dir .. Branch.sep .. '.git' + local git_path = root_dir .. sep .. '.git' local git_file_stat = vim.loop.fs_stat(git_path) if git_file_stat then if git_file_stat.type == 'directory' then @@ -66,12 +79,12 @@ function Branch.find_git_dir() git_dir = git_dir:match 'gitdir: (.+)$' file:close() -- submodule / relative file path - if git_dir and git_dir:sub(1, 1) ~= Branch.sep and not git_dir:match '^%a:.*$' then + if git_dir and git_dir:sub(1, 1) ~= sep and not git_dir:match '^%a:.*$' then git_dir = git_path:match '(.*).git' .. git_dir end end if git_dir then - local head_file_stat = vim.loop.fs_stat(git_dir .. Branch.sep .. 'HEAD') + local head_file_stat = vim.loop.fs_stat(git_dir .. sep .. 'HEAD') if head_file_stat and head_file_stat.type == 'file' then break else @@ -79,54 +92,34 @@ function Branch.find_git_dir() end end end - root_dir = root_dir:match('(.*)' .. Branch.sep .. '.-') + root_dir = root_dir:match('(.*)' .. sep .. '.-') end git_dir_cache[file_dir] = git_dir - if Branch.git_dir ~= git_dir then - Branch.git_dir = git_dir - Branch.update_branch() + if dir_path == nil and current_git_dir ~= git_dir then + current_git_dir = git_dir + update_branch() end return git_dir end --- sets git_branch veriable to branch name or commit hash if not on branch -function Branch.get_git_head(head_file) - local f_head = io.open(head_file) - if f_head then - local HEAD = f_head:read() - f_head:close() - local branch = HEAD:match 'ref: refs/heads/(.+)$' - if branch then - Branch.git_branch = branch - else - Branch.git_branch = HEAD:sub(1, 6) - end +function M.init() + -- run watch head on load so branch is present when component is loaded + M.find_git_dir() + -- update branch state of BufEnter as different Buffer may be on different repos + utils.define_autocmd('BufEnter', "lua require'lualine.components.branch.git_branch'.find_git_dir()") +end +function M.get_branch(bufnr) + if vim.g.actual_curbuf ~= nil and active_bufnr ~= vim.g.actual_curbuf then + -- Workaround for https://github.com/hoob3rt/lualine.nvim/issues/286 + -- See upstream issue https://github.com/neovim/neovim/issues/15300 + -- Diff is out of sync re sync it. + M.find_git_dir() end - return nil + if bufnr then + return branch_cache[bufnr] or '' + end + return current_git_branch end --- Update branch -function Branch.update_branch() - Branch.active_bufnr = tostring(vim.fn.bufnr()) - Branch.file_changed:stop() - local git_dir = Branch.git_dir - if git_dir and #git_dir > 0 then - local head_file = git_dir .. Branch.sep .. 'HEAD' - Branch.get_git_head(head_file) - Branch.file_changed:start( - head_file, - Branch.sep ~= '\\' and {} or 1000, - vim.schedule_wrap(function() - -- reset file-watch - Branch.update_branch() - end) - ) - else - -- set to '' when git dir was not found - Branch.git_branch = '' - end - branch_cache[vim.fn.bufnr()] = Branch.git_branch -end - -return Branch +return M diff --git a/lua/lualine/components/branch/init.lua b/lua/lualine/components/branch/init.lua new file mode 100644 index 0000000..1c5b6b1 --- /dev/null +++ b/lua/lualine/components/branch/init.lua @@ -0,0 +1,20 @@ +-- Copyright (c) 2020-2021 shadmansaleh +-- MIT license, see LICENSE for more details. +local M = require('lualine.component'):extend() +local require = require('lualine_require').require +local git_branch = require 'lualine.components.branch.git_branch' + +-- Initilizer +M.init = function(self, options) + M.super.init(self, options) + if not self.options.icon then + self.options.icon = '' -- e0a0 + end + git_branch.init() +end + +M.update_status = function(_, is_focused) + return git_branch.get_branch((not is_focused and vim.fn.bufnr())) +end + +return M diff --git a/lua/lualine/components/buffers.lua b/lua/lualine/components/buffers.lua deleted file mode 100644 index 4bafc41..0000000 --- a/lua/lualine/components/buffers.lua +++ /dev/null @@ -1,270 +0,0 @@ --- Copyright (c) 2020-2021 shadmansaleh --- MIT license, see LICENSE for more details. -local Buffers = require('lualine.component'):new() -local highlight = require 'lualine.highlight' - -local default_options = { - show_filename_only = true, - show_modified_status = true, - max_length = 0, - filetype_names = { - TelescopePrompt = 'Telescope', - dashboard = 'Dashboard', - packer = 'Packer', - fzf = 'FZF', - alpha = 'Alpha', - }, - buffers_color = { - active = nil, - inactive = nil, - }, -} - -local function get_hl(section, is_active) - local suffix = is_active and '_normal' or '_inactive' - local section_redirects = { - lualine_x = 'lualine_c', - lualine_y = 'lualine_b', - lualine_z = 'lualine_a', - } - if section_redirects[section] then - section = highlight.highlight_exists(section .. suffix) and section or section_redirects[section] - end - return section .. suffix -end - -local Buffer = {} - -function Buffer:new(buffer) - assert(buffer.bufnr, 'Cannot create Buffer without bufnr') - local newObj = { bufnr = buffer.bufnr, options = buffer.options, highlights = buffer.highlights } - self.__index = self - newObj = setmetatable(newObj, self) - newObj:get_props() - return newObj -end - -function Buffer:get_props() - self.file = vim.fn.bufname(self.bufnr) - self.buftype = vim.api.nvim_buf_get_option(self.bufnr, 'buftype') - self.filetype = vim.api.nvim_buf_get_option(self.bufnr, 'filetype') - local modified = self.options.show_modified_status and vim.api.nvim_buf_get_option(self.bufnr, 'modified') - local modified_icon = self.options.icons_enabled and ' ●' or ' +' - self.modified_icon = modified and modified_icon or '' - self.icon = '' - if self.options.icons_enabled then - local dev - local status, _ = pcall(require, 'nvim-web-devicons') - if not status then - dev, _ = '', '' - elseif self.filetype == 'TelescopePrompt' then - dev, _ = require('nvim-web-devicons').get_icon 'telescope' - elseif self.filetype == 'fugitive' then - dev, _ = require('nvim-web-devicons').get_icon 'git' - elseif self.filetype == 'vimwiki' then - dev, _ = require('nvim-web-devicons').get_icon 'markdown' - elseif self.buftype == 'terminal' then - dev, _ = require('nvim-web-devicons').get_icon 'zsh' - elseif vim.fn.isdirectory(self.file) == 1 then - dev, _ = '', nil - else - dev, _ = require('nvim-web-devicons').get_icon(self.file, vim.fn.expand('#' .. self.bufnr .. ':e')) - end - if dev then - self.icon = dev .. ' ' - end - end - return self -end - -function Buffer:render() - local name - if self.ellipse then - name = '...' - else - name = string.format(' %s%s%s ', self.icon, self:name(), self.modified_icon) - end - self.len = vim.fn.strchars(name) - - local line = string.format('%%%s@LualineSwitchBuffer@%s%%T', self.bufnr, name) - line = highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')]) .. line - - if self.options.self.section < 'lualine_x' and not self.first then - local sep_before = self:separator_before() - line = sep_before .. line - self.len = self.len + vim.fn.strchars(sep_before) - elseif self.options.self.section >= 'lualine_x' and not self.last then - local sep_after = self:separator_after() - line = line .. sep_after - self.len = self.len + vim.fn.strchars(sep_after) - end - return line -end - -function Buffer:separator_before() - if self.current or self.aftercurrent then - return '%S{' .. self.options.section_separators.left .. '}' - else - return self.options.component_separators.left - end -end - -function Buffer:separator_after() - if self.current or self.beforecurrent then - return '%s{' .. self.options.section_separators.right .. '}' - else - return self.options.component_separators.right - end -end - -function Buffer:name() - if self.options.filetype_names[self.filetype] then - return self.options.filetype_names[self.filetype] - elseif self.buftype == 'help' then - return 'help:' .. vim.fn.fnamemodify(self.file, ':t:r') - elseif self.buftype == 'terminal' then - local match = string.match(vim.split(self.file, ' ')[1], 'term:.*:(%a+)') - return match ~= nil and match or vim.fn.fnamemodify(vim.env.SHELL, ':t') - elseif vim.fn.isdirectory(self.file) == 1 then - return vim.fn.fnamemodify(self.file, ':p:.') - elseif self.file == '' then - return '[No Name]' - end - return self.options.show_filename_only and vim.fn.fnamemodify(self.file, ':t') - or vim.fn.pathshorten(vim.fn.fnamemodify(self.file, ':p:.')) -end - -function Buffers:new(options, child) - local newObj = self._parent:new(options, child or Buffers) - default_options.buffers_color = { - active = get_hl(options.self.section, true), - inactive = get_hl(options.self.section, false), - } - newObj.options = vim.tbl_deep_extend('keep', newObj.options or {}, default_options) - newObj.highlights = { - active = highlight.create_component_highlight_group( - newObj.options.buffers_color.active, - 'buffers_active', - newObj.options - ), - inactive = highlight.create_component_highlight_group( - newObj.options.buffers_color.inactive, - 'buffers_active', - newObj.options - ), - } - return newObj -end - -function Buffers:update_status() - local data = {} - local buffers = {} - for b = 1, vim.fn.bufnr '$' do - if vim.fn.buflisted(b) ~= 0 and vim.api.nvim_buf_get_option(b, 'buftype') ~= 'quickfix' then - buffers[#buffers + 1] = Buffer:new { bufnr = b, options = self.options, highlights = self.highlights } - end - end - local current_bufnr = vim.fn.bufnr() - local current = -2 - if buffers[1] then - buffers[1].first = true - end - if buffers[#buffers] then - buffers[#buffers].last = true - end - for i, buffer in ipairs(buffers) do - if buffer.bufnr == current_bufnr then - buffer.current = true - current = i - end - end - if buffers[current - 1] then - buffers[current - 1].beforecurrent = true - end - if buffers[current + 1] then - buffers[current + 1].aftercurrent = true - end - - local max_length = self.options.max_length - if max_length == 0 then - max_length = math.floor(2 * vim.o.columns / 3) - end - local total_length - for i, buffer in pairs(buffers) do - if buffer.current then - current = i - end - end - if current == -2 then - local b = Buffer:new { bufnr = vim.fn.bufnr(), options = self.options, highlights = self.highlights } - b.current = true - if self.options.self.section < 'lualine_x' then - b.last = true - if #buffers > 0 then - buffers[#buffers].last = nil - end - buffers[#buffers + 1] = b - current = #buffers - else - b.first = true - if #buffers > 0 then - buffers[1].first = nil - end - table.insert(buffers, 1, b) - current = 1 - end - end - local current_buffer = buffers[current] - data[#data + 1] = current_buffer:render() - total_length = current_buffer.len - local i = 0 - local before, after - while true do - i = i + 1 - before = buffers[current - i] - after = buffers[current + i] - local rendered_before, rendered_after - if before == nil and after == nil then - break - end - if before then - rendered_before = before:render() - total_length = total_length + before.len - end - if after then - rendered_after = after:render() - total_length = total_length + after.len - end - if total_length > max_length then - break - end - if before then - table.insert(data, 1, rendered_before) - end - if after then - data[#data + 1] = rendered_after - end - end - if total_length > max_length then - if before ~= nil then - before.ellipse = true - before.first = true - table.insert(data, 1, before:render()) - end - if after ~= nil then - after.ellipse = true - after.last = true - data[#data + 1] = after:render() - end - end - - return table.concat(data) -end - -vim.cmd [[ - function! LualineSwitchBuffer(bufnr, mouseclicks, mousebutton, modifiers) - execute ":buffer " . a:bufnr - endfunction -]] - -return Buffers diff --git a/lua/lualine/components/buffers/buffer.lua b/lua/lualine/components/buffers/buffer.lua new file mode 100644 index 0000000..2fd811d --- /dev/null +++ b/lua/lualine/components/buffers/buffer.lua @@ -0,0 +1,103 @@ +local highlight = require 'lualine.highlight' + +local Buffer = require('lualine.utils.class'):extend() + +function Buffer:init(opts) + assert(opts.bufnr, 'Cannot create Buffer without bufnr') + self.bufnr = opts.bufnr + self.options = opts.options + self.highlights = opts.highlights + self:get_props() +end + +function Buffer:get_props() + self.file = vim.fn.bufname(self.bufnr) + self.buftype = vim.api.nvim_buf_get_option(self.bufnr, 'buftype') + self.filetype = vim.api.nvim_buf_get_option(self.bufnr, 'filetype') + local modified = self.options.show_modified_status and vim.api.nvim_buf_get_option(self.bufnr, 'modified') + local modified_icon = self.options.icons_enabled and ' ●' or ' +' + self.modified_icon = modified and modified_icon or '' + self.icon = '' + if self.options.icons_enabled then + local dev + local status, _ = pcall(require, 'nvim-web-devicons') + if not status then + dev, _ = '', '' + elseif self.filetype == 'TelescopePrompt' then + dev, _ = require('nvim-web-devicons').get_icon 'telescope' + elseif self.filetype == 'fugitive' then + dev, _ = require('nvim-web-devicons').get_icon 'git' + elseif self.filetype == 'vimwiki' then + dev, _ = require('nvim-web-devicons').get_icon 'markdown' + elseif self.buftype == 'terminal' then + dev, _ = require('nvim-web-devicons').get_icon 'zsh' + elseif vim.fn.isdirectory(self.file) == 1 then + dev, _ = '', nil + else + dev, _ = require('nvim-web-devicons').get_icon(self.file, vim.fn.expand('#' .. self.bufnr .. ':e')) + end + if dev then + self.icon = dev .. ' ' + end + end + return self +end + +function Buffer:render() + local name + if self.ellipse then + name = '...' + else + name = string.format(' %s%s%s ', self.icon, self:name(), self.modified_icon) + end + self.len = vim.fn.strchars(name) + + local line = string.format('%%%s@LualineSwitchBuffer@%s%%T', self.bufnr, name) + line = highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')]) .. line + + if self.options.self.section < 'lualine_x' and not self.first then + local sep_before = self:separator_before() + line = sep_before .. line + self.len = self.len + vim.fn.strchars(sep_before) + elseif self.options.self.section >= 'lualine_x' and not self.last then + local sep_after = self:separator_after() + line = line .. sep_after + self.len = self.len + vim.fn.strchars(sep_after) + end + return line +end + +function Buffer:separator_before() + if self.current or self.aftercurrent then + return '%S{' .. self.options.section_separators.left .. '}' + else + return self.options.component_separators.left + end +end + +function Buffer:separator_after() + if self.current or self.beforecurrent then + return '%s{' .. self.options.section_separators.right .. '}' + else + return self.options.component_separators.right + end +end + +function Buffer:name() + if self.options.filetype_names[self.filetype] then + return self.options.filetype_names[self.filetype] + elseif self.buftype == 'help' then + return 'help:' .. vim.fn.fnamemodify(self.file, ':t:r') + elseif self.buftype == 'terminal' then + local match = string.match(vim.split(self.file, ' ')[1], 'term:.*:(%a+)') + return match ~= nil and match or vim.fn.fnamemodify(vim.env.SHELL, ':t') + elseif vim.fn.isdirectory(self.file) == 1 then + return vim.fn.fnamemodify(self.file, ':p:.') + elseif self.file == '' then + return '[No Name]' + end + return self.options.show_filename_only and vim.fn.fnamemodify(self.file, ':t') + or vim.fn.pathshorten(vim.fn.fnamemodify(self.file, ':p:.')) +end + +return Buffer diff --git a/lua/lualine/components/buffers/init.lua b/lua/lualine/components/buffers/init.lua new file mode 100644 index 0000000..a2f0f87 --- /dev/null +++ b/lua/lualine/components/buffers/init.lua @@ -0,0 +1,170 @@ +-- Copyright (c) 2020-2021 shadmansaleh +-- MIT license, see LICENSE for more details. +local require = require('lualine_require').require +local Buffer = require 'lualine.components.buffers.buffer' +local M = require('lualine.component'):extend() +local highlight = require 'lualine.highlight' + +local default_options = { + show_filename_only = true, + show_modified_status = true, + max_length = 0, + filetype_names = { + TelescopePrompt = 'Telescope', + dashboard = 'Dashboard', + packer = 'Packer', + fzf = 'FZF', + alpha = 'Alpha', + }, + buffers_color = { + active = nil, + inactive = nil, + }, +} + +local function get_hl(section, is_active) + local suffix = is_active and '_normal' or '_inactive' + local section_redirects = { + lualine_x = 'lualine_c', + lualine_y = 'lualine_b', + lualine_z = 'lualine_a', + } + if section_redirects[section] then + section = highlight.highlight_exists(section .. suffix) and section or section_redirects[section] + end + return section .. suffix +end + +function M:init(options) + M.super.init(self, options) + default_options.buffers_color = { + active = get_hl(options.self.section, true), + inactive = get_hl(options.self.section, false), + } + self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options) + self.highlights = { + active = highlight.create_component_highlight_group( + self.options.buffers_color.active, + 'buffers_active', + self.options + ), + inactive = highlight.create_component_highlight_group( + self.options.buffers_color.inactive, + 'buffers_active', + self.options + ), + } +end + +function M:update_status() + local data = {} + local buffers = {} + for b = 1, vim.fn.bufnr '$' do + if vim.fn.buflisted(b) ~= 0 and vim.api.nvim_buf_get_option(b, 'buftype') ~= 'quickfix' then + buffers[#buffers + 1] = Buffer { bufnr = b, options = self.options, highlights = self.highlights } + end + end + local current_bufnr = vim.fn.bufnr() + local current = -2 + if buffers[1] then + buffers[1].first = true + end + if buffers[#buffers] then + buffers[#buffers].last = true + end + for i, buffer in ipairs(buffers) do + if buffer.bufnr == current_bufnr then + buffer.current = true + current = i + end + end + if buffers[current - 1] then + buffers[current - 1].beforecurrent = true + end + if buffers[current + 1] then + buffers[current + 1].aftercurrent = true + end + + local max_length = self.options.max_length + if max_length == 0 then + max_length = math.floor(2 * vim.o.columns / 3) + end + local total_length + for i, buffer in pairs(buffers) do + if buffer.current then + current = i + end + end + if current == -2 then + local b = Buffer { bufnr = vim.fn.bufnr(), options = self.options, highlights = self.highlights } + b.current = true + if self.options.self.section < 'lualine_x' then + b.last = true + if #buffers > 0 then + buffers[#buffers].last = nil + end + buffers[#buffers + 1] = b + current = #buffers + else + b.first = true + if #buffers > 0 then + buffers[1].first = nil + end + table.insert(buffers, 1, b) + current = 1 + end + end + local current_buffer = buffers[current] + data[#data + 1] = current_buffer:render() + total_length = current_buffer.len + local i = 0 + local before, after + while true do + i = i + 1 + before = buffers[current - i] + after = buffers[current + i] + local rendered_before, rendered_after + if before == nil and after == nil then + break + end + if before then + rendered_before = before:render() + total_length = total_length + before.len + end + if after then + rendered_after = after:render() + total_length = total_length + after.len + end + if total_length > max_length then + break + end + if before then + table.insert(data, 1, rendered_before) + end + if after then + data[#data + 1] = rendered_after + end + end + if total_length > max_length then + if before ~= nil then + before.ellipse = true + before.first = true + table.insert(data, 1, before:render()) + end + if after ~= nil then + after.ellipse = true + after.last = true + data[#data + 1] = after:render() + end + end + + return table.concat(data) +end + +vim.cmd [[ + function! LualineSwitchBuffer(bufnr, mouseclicks, mousebutton, modifiers) + execute ":buffer " . a:bufnr + endfunction +]] + +return M diff --git a/lua/lualine/components/diagnostics.lua b/lua/lualine/components/diagnostics.lua deleted file mode 100644 index a8f915b..0000000 --- a/lua/lualine/components/diagnostics.lua +++ /dev/null @@ -1,248 +0,0 @@ --- Copyright (c) 2020-2021 hoob3rt --- MIT license, see LICENSE for more details. -local lualine_require = require 'lualine_require' -local modules = lualine_require.lazy_require { - highlight = 'lualine.highlight', - utils = 'lualine.utils.utils', - utils_notices = 'lualine.utils.notices', -} - -local Diagnostics = lualine_require.require('lualine.component'):new() - -local function check_deprecated_options(options) - if options.color_error or options.color_warn or options.color_info or options.color_hint then - options.diagnostics_color = options.diagnostics_color or {} - require('lualine.utils.notices').add_notice(string.format [[ -### diagnostics.options.colors -Previously colors in diagnostics section was set with color_error, color_warning.. -separate options . They've been unified under diagnostics_color options. -Now it should be something like: -```lua -{ 'diagnostics', - sources = {'nvim_lsp'}, - diagnostics_color = { - error = color_error, - warning = color_warning, - info = color_info, - hint = color_hint, - } -} -``` -]]) - options.diagnostics_color.error = options.color_error - options.diagnostics_color.warning = options.color_warning - options.diagnostics_color.info = options.color_info - options.diagnostics_color.hint = options.color_hint - end -end - -local default_symbols = { - icons = { - error = ' ', -- xf659 - warn = ' ', -- xf529 - info = ' ', -- xf7fc - hint = ' ', -- xf838 - }, - no_icons = { error = 'E:', warn = 'W:', info = 'I:', hint = 'H:' }, -} - -local default_options = { - colored = true, - update_in_insert = false, - sources = { 'nvim_lsp', 'coc' }, - sections = { 'error', 'warn', 'info', 'hint' }, - diagnostics_color = { - error = { - fg = modules.utils.extract_color_from_hllist( - 'fg', - { 'DiagnosticError', 'LspDiagnosticsDefaultError', 'DiffDelete' }, - '#e32636' - ), - }, - warn = { - fg = modules.utils.extract_color_from_hllist( - 'fg', - { 'DiagnosticWarn', 'LspDiagnosticsDefaultWarning', 'DiffText' }, - '#ffa500' - ), - }, - info = { - fg = modules.utils.extract_color_from_hllist( - 'fg', - { 'DiagnosticInfo', 'LspDiagnosticsDefaultInformation', 'Normal' }, - '#ffffff' - ), - }, - hint = { - fg = modules.utils.extract_color_from_hllist( - 'fg', - { 'DiagnosticHint', 'LspDiagnosticsDefaultHint', 'DiffChange' }, - '#273faf' - ), - }, - }, -} --- Initializer -Diagnostics.new = function(self, options, child) - -- Run super() - local new_diagnostics = self._parent:new(options, child or Diagnostics) - -- Apply default options - new_diagnostics.options = vim.tbl_deep_extend('keep', new_diagnostics.options or {}, default_options) - check_deprecated_options(new_diagnostics.options) - -- Apply default symbols - new_diagnostics.symbols = vim.tbl_extend( - 'keep', - new_diagnostics.options.symbols or {}, - new_diagnostics.options.icons_enabled ~= false and default_symbols.icons or default_symbols.no_icons - ) - -- Initialize highlight groups - if new_diagnostics.options.colored then - new_diagnostics.highlight_groups = { - error = modules.highlight.create_component_highlight_group( - new_diagnostics.options.diagnostics_color.error, - 'diagnostics_error', - new_diagnostics.options - ), - warn = modules.highlight.create_component_highlight_group( - new_diagnostics.options.diagnostics_color.warn, - 'diagnostics_warn', - new_diagnostics.options - ), - info = modules.highlight.create_component_highlight_group( - new_diagnostics.options.diagnostics_color.info, - 'diagnostics_info', - new_diagnostics.options - ), - hint = modules.highlight.create_component_highlight_group( - new_diagnostics.options.diagnostics_color.hint, - 'diagnostics_hint', - new_diagnostics.options - ), - } - end - - -- Error out no source - if #new_diagnostics.options.sources < 1 then - print 'no sources for diagnostics configured' - return '' - end - -- Initialize variable to store last update so we can use it in insert - -- mode for no update_in_insert - new_diagnostics.last_update = '' - return new_diagnostics -end - -Diagnostics.update_status = function(self) - if not self.options.update_in_insert and vim.api.nvim_get_mode().mode:sub(1, 1) == 'i' then - return self.last_update - end - local error_count, warning_count, info_count, hint_count = 0, 0, 0, 0 - local diagnostic_data = self.get_diagnostics(self.options.sources) - for _, data in pairs(diagnostic_data) do - error_count = error_count + data.error - warning_count = warning_count + data.warn - info_count = info_count + data.info - hint_count = hint_count + data.hint - end - local result = {} - local data = { - error = error_count, - warn = warning_count, - info = info_count, - hint = hint_count, - } - if self.options.colored then - local colors = {} - for name, hl in pairs(self.highlight_groups) do - colors[name] = modules.highlight.component_format_highlight(hl) - end - for _, section in ipairs(self.options.sections) do - if data[section] ~= nil and data[section] > 0 then - table.insert(result, colors[section] .. self.symbols[section] .. data[section]) - end - end - else - for _, section in ipairs(self.options.sections) do - if data[section] ~= nil and data[section] > 0 then - table.insert(result, self.symbols[section] .. data[section]) - end - end - end - self.last_update = '' - if result[1] ~= nil then - self.last_update = table.concat(result, ' ') - end - return self.last_update -end - -Diagnostics.diagnostic_sources = { - nvim_lsp = function() - local error_count = vim.lsp.diagnostic.get_count(0, 'Error') - local warning_count = vim.lsp.diagnostic.get_count(0, 'Warning') - local info_count = vim.lsp.diagnostic.get_count(0, 'Information') - local hint_count = vim.lsp.diagnostic.get_count(0, 'Hint') - return error_count, warning_count, info_count, hint_count - end, - nvim = function() - local diagnostics = vim.diagnostic.get(0) - local count = { 0, 0, 0, 0 } - for _, diagnostic in ipairs(diagnostics) do - count[diagnostic.severity] = count[diagnostic.severity] + 1 - end - return count[vim.diagnostic.severity.ERROR], - count[vim.diagnostic.severity.WARN], - count[vim.diagnostic.severity.INFO], - count[vim.diagnostic.severity.HINT] - end, - coc = function() - local data = vim.b.coc_diagnostic_info - if data then - return data.error, data.warning, data.information, data.hint - else - return 0, 0, 0, 0 - end - end, - ale = function() - local ok, data = pcall(vim.fn['ale#statusline#Count'], vim.fn.bufnr()) - if ok then - return data.error + data.style_error, data.warning + data.style_warning, data.info, 0 - else - return 0, 0, 0, 0 - end - end, - vim_lsp = function() - local ok, data = pcall(vim.fn['lsp#get_buffer_diagnostics_counts']) - if ok then - return data.error, data.warning, data.information - else - return 0, 0, 0 - end - end, -} - -Diagnostics.get_diagnostics = function(sources) - local result = {} - for index, source in ipairs(sources) do - if type(source) == 'string' then - local error_count, warning_count, info_count, hint_count = Diagnostics.diagnostic_sources[source]() - result[index] = { - error = error_count, - warn = warning_count, - info = info_count, - hint = hint_count, - } - elseif type(source) == 'function' then - local source_result = source() - source_result = type(source_result) == 'table' and source_result or {} - result[index] = { - error = source_result.error or 0, - warn = source_result.warn or 0, - info = source_result.info or 0, - hint = source_result.hint or 0, - } - end - end - return result -end - -return Diagnostics diff --git a/lua/lualine/components/diagnostics/config.lua b/lua/lualine/components/diagnostics/config.lua new file mode 100644 index 0000000..4beb9b3 --- /dev/null +++ b/lua/lualine/components/diagnostics/config.lua @@ -0,0 +1,52 @@ +local require = require('lualine_require').require +local utils = require 'lualine.utils.utils' +local M = {} + +M.symbols = { + icons = { + error = ' ', -- xf659 + warn = ' ', -- xf529 + info = ' ', -- xf7fc + hint = ' ', -- xf838 + }, + no_icons = { error = 'E:', warn = 'W:', info = 'I:', hint = 'H:' }, +} + +M.options = { + colored = true, + update_in_insert = false, + sources = { 'nvim_lsp', 'coc' }, + sections = { 'error', 'warn', 'info', 'hint' }, + diagnostics_color = { + error = { + fg = utils.extract_color_from_hllist( + 'fg', + { 'DiagnosticError', 'LspDiagnosticsDefaultError', 'DiffDelete' }, + '#e32636' + ), + }, + warn = { + fg = utils.extract_color_from_hllist( + 'fg', + { 'DiagnosticWarn', 'LspDiagnosticsDefaultWarning', 'DiffText' }, + '#ffa500' + ), + }, + info = { + fg = utils.extract_color_from_hllist( + 'fg', + { 'DiagnosticInfo', 'LspDiagnosticsDefaultInformation', 'Normal' }, + '#ffffff' + ), + }, + hint = { + fg = utils.extract_color_from_hllist( + 'fg', + { 'DiagnosticHint', 'LspDiagnosticsDefaultHint', 'DiffChange' }, + '#273faf' + ), + }, + }, +} + +return M diff --git a/lua/lualine/components/diagnostics/init.lua b/lua/lualine/components/diagnostics/init.lua new file mode 100644 index 0000000..c5a19fe --- /dev/null +++ b/lua/lualine/components/diagnostics/init.lua @@ -0,0 +1,109 @@ +-- Copyright (c) 2020-2021 hoob3rt +-- MIT license, see LICENSE for more details. +local lualine_require = require 'lualine_require' +local modules = lualine_require.lazy_require { + default_config = 'lualine.components.diagnostics.config', + sources = 'lualine.components.diagnostics.sources', + highlight = 'lualine.highlight', + utils = 'lualine.utils.utils', + utils_notices = 'lualine.utils.notices', +} + +local M = lualine_require.require('lualine.component'):extend() + +M.diagnostics_sources = modules.sources.sources +M.get_diagnostics = modules.sources.get_diagnostics + +-- Initializer +function M:init(options) + -- Run super() + M.super.init(self, options) + -- Apply default options + self.options = vim.tbl_deep_extend('keep', self.options or {}, modules.default_config.options) + -- Apply default symbols + self.symbols = vim.tbl_extend( + 'keep', + self.options.symbols or {}, + self.options.icons_enabled ~= false and modules.default_config.symbols.icons + or modules.default_config.symbols.no_icons + ) + -- Initialize highlight groups + if self.options.colored then + self.highlight_groups = { + error = modules.highlight.create_component_highlight_group( + self.options.diagnostics_color.error, + 'diagnostics_error', + self.options + ), + warn = modules.highlight.create_component_highlight_group( + self.options.diagnostics_color.warn, + 'diagnostics_warn', + self.options + ), + info = modules.highlight.create_component_highlight_group( + self.options.diagnostics_color.info, + 'diagnostics_info', + self.options + ), + hint = modules.highlight.create_component_highlight_group( + self.options.diagnostics_color.hint, + 'diagnostics_hint', + self.options + ), + } + end + + -- Error out no source + if #self.options.sources < 1 then + print 'no sources for diagnostics configured' + return '' + end + -- Initialize variable to store last update so we can use it in insert + -- mode for no update_in_insert + self.last_update = '' +end + +function M:update_status() + if not self.options.update_in_insert and vim.api.nvim_get_mode().mode:sub(1, 1) == 'i' then + return self.last_update + end + local error_count, warning_count, info_count, hint_count = 0, 0, 0, 0 + local diagnostic_data = modules.sources.get_diagnostics(self.options.sources) + for _, data in pairs(diagnostic_data) do + error_count = error_count + data.error + warning_count = warning_count + data.warn + info_count = info_count + data.info + hint_count = hint_count + data.hint + end + local result = {} + local data = { + error = error_count, + warn = warning_count, + info = info_count, + hint = hint_count, + } + if self.options.colored then + local colors = {} + for name, hl in pairs(self.highlight_groups) do + colors[name] = modules.highlight.component_format_highlight(hl) + end + for _, section in ipairs(self.options.sections) do + if data[section] ~= nil and data[section] > 0 then + table.insert(result, colors[section] .. self.symbols[section] .. data[section]) + end + end + else + for _, section in ipairs(self.options.sections) do + if data[section] ~= nil and data[section] > 0 then + table.insert(result, self.symbols[section] .. data[section]) + end + end + end + self.last_update = '' + if result[1] ~= nil then + self.last_update = table.concat(result, ' ') + end + return self.last_update +end + +return M diff --git a/lua/lualine/components/diagnostics/sources.lua b/lua/lualine/components/diagnostics/sources.lua new file mode 100644 index 0000000..f221673 --- /dev/null +++ b/lua/lualine/components/diagnostics/sources.lua @@ -0,0 +1,73 @@ +local M = {} + +M.sources = { + nvim_lsp = function() + local error_count = vim.lsp.diagnostic.get_count(0, 'Error') + local warning_count = vim.lsp.diagnostic.get_count(0, 'Warning') + local info_count = vim.lsp.diagnostic.get_count(0, 'Information') + local hint_count = vim.lsp.diagnostic.get_count(0, 'Hint') + return error_count, warning_count, info_count, hint_count + end, + nvim = function() + local diagnostics = vim.diagnostic.get(0) + local count = { 0, 0, 0, 0 } + for _, diagnostic in ipairs(diagnostics) do + count[diagnostic.severity] = count[diagnostic.severity] + 1 + end + return count[vim.diagnostic.severity.ERROR], + count[vim.diagnostic.severity.WARN], + count[vim.diagnostic.severity.INFO], + count[vim.diagnostic.severity.HINT] + end, + coc = function() + local data = vim.b.coc_diagnostic_info + if data then + return data.error, data.warning, data.information, data.hint + else + return 0, 0, 0, 0 + end + end, + ale = function() + local ok, data = pcall(vim.fn['ale#statusline#Count'], vim.fn.bufnr()) + if ok then + return data.error + data.style_error, data.warning + data.style_warning, data.info, 0 + else + return 0, 0, 0, 0 + end + end, + vim_lsp = function() + local ok, data = pcall(vim.fn['lsp#get_buffer_diagnostics_counts']) + if ok then + return data.error, data.warning, data.information + else + return 0, 0, 0 + end + end, +} + +M.get_diagnostics = function(sources) + local result = {} + for index, source in ipairs(sources) do + if type(source) == 'string' then + local error_count, warning_count, info_count, hint_count = M.sources[source]() + result[index] = { + error = error_count, + warn = warning_count, + info = info_count, + hint = hint_count, + } + elseif type(source) == 'function' then + local source_result = source() + source_result = type(source_result) == 'table' and source_result or {} + result[index] = { + error = source_result.error or 0, + warn = source_result.warn or 0, + info = source_result.info or 0, + hint = source_result.hint or 0, + } + end + end + return result +end + +return M diff --git a/lua/lualine/components/diff.lua b/lua/lualine/components/diff.lua deleted file mode 100644 index f0fd098..0000000 --- a/lua/lualine/components/diff.lua +++ /dev/null @@ -1,244 +0,0 @@ --- Copyright (c) 2020-2021 shadmansaleh --- MIT license, see LICENSE for more details. -local lualine_require = require 'lualine_require' -local modules = lualine_require.lazy_require { - utils = 'lualine.utils.utils', - utils_notices = 'lualine.utils.notices', - highlight = 'lualine.highlight', - Job = 'lualine.utils.job', -} -local Diff = lualine_require.require('lualine.component'):new() - -local function check_deprecated_options(options) - if options.color_added or options.color_modified or options.color_removed then - options.diagnostics_color = options.diagnostics_color or {} - require('lualine.utils.notices').add_notice(string.format [[ -### diff.options.colors -Previously colors in diff section was set with color_added, color_modified.. -separate options . They've been unified under diff_color option. -Now it should be something like: -```lua -{ 'diff', - diff_color = { - added = color_added, - modified = color_modified, - removed = color_removed, - } -} -``` -]]) - options.diff_color.added = options.color_added - options.diff_color.modified = options.color_modified - options.diff_color.removed = options.color_removed - end -end - --- Vars --- variable to store git diff stats -Diff.git_diff = nil --- accumulates output from diff process -Diff.diff_output_cache = {} --- variable to store git_diff job -Diff.diff_job = nil -Diff.active_bufnr = '0' - -local diff_cache = {} -- Stores last known value of diff of a buffer - -local default_options = { - colored = true, - symbols = { added = '+', modified = '~', removed = '-' }, - diff_color = { - added = { - fg = modules.utils.extract_highlight_colors('DiffAdd', 'fg') or '#f0e130', - }, - modified = { - fg = modules.utils.extract_highlight_colors('DiffChange', 'fg') or '#ff0038', - }, - removed = { - fg = modules.utils.extract_highlight_colors('DiffDelete', 'fg') or '#ff0038', - }, - }, -} - --- Initializer -Diff.new = function(self, options, child) - local new_instance = self._parent:new(options, child or Diff) - new_instance.options = vim.tbl_deep_extend('keep', new_instance.options or {}, default_options) - check_deprecated_options(new_instance.options) - -- create highlights and save highlight_name in highlights table - if new_instance.options.colored then - new_instance.highlights = { - added = modules.highlight.create_component_highlight_group( - new_instance.options.diff_color.added, - 'diff_added', - new_instance.options - ), - modified = modules.highlight.create_component_highlight_group( - new_instance.options.diff_color.modified, - 'diff_modified', - new_instance.options - ), - removed = modules.highlight.create_component_highlight_group( - new_instance.options.diff_color.removed, - 'diff_removed', - new_instance.options - ), - } - end - - Diff.diff_checker_enabled = type(new_instance.options.source) ~= 'function' - - if Diff.diff_checker_enabled then - -- setup internal source - modules.utils.define_autocmd('BufEnter', "lua require'lualine.components.diff'.update_diff_args()") - modules.utils.define_autocmd('BufWritePost', "lua require'lualine.components.diff'.update_git_diff()") - Diff.update_diff_args() - end - - return new_instance -end - --- Function that runs everytime statusline is updated -Diff.update_status = function(self, is_focused) - local git_diff - if Diff.diff_checker_enabled then - if Diff.active_bufnr ~= vim.g.actual_curbuf then - -- Workaround for https://github.com/hoob3rt/lualine.nvim/issues/286 - -- See upstream issue https://github.com/neovim/neovim/issues/15300 - -- Diff is out of sync re sync it. - Diff.update_diff_args() - end - git_diff = Diff.git_diff - else - git_diff = self.options.source() - 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 - -- load the highlights and store them in colors table - for name, highlight_name in pairs(self.highlights) do - colors[name] = modules.highlight.component_format_highlight(highlight_name) - end - end - - local result = {} - -- loop though data and load available sections in result table - for _, name in ipairs { 'added', 'modified', 'removed' } do - if git_diff[name] and git_diff[name] > 0 then - if self.options.colored then - table.insert(result, colors[name] .. self.options.symbols[name] .. git_diff[name]) - else - table.insert(result, self.options.symbols[name] .. git_diff[name]) - end - end - end - if #result > 0 then - return table.concat(result, ' ') - else - return '' - end -end - --- Api to get git sign count --- scheme : --- { --- added = added_count, --- modified = modified_count, --- removed = removed_count, --- } --- error_code = { added = -1, modified = -1, removed = -1 } -function Diff.get_sign_count() - if Diff.diff_checker_enabled then - Diff.update_diff_args() - end - return Diff.git_diff or { added = -1, modified = -1, removed = -1 } -end - --- process diff data and update git_diff{ added, removed, modified } -function Diff.process_diff(data) - -- Adapted from https://github.com/wbthomason/nvim-vcs.lua - local added, removed, modified = 0, 0, 0 - for _, line in ipairs(data) do - if string.find(line, [[^@@ ]]) then - local tokens = vim.fn.matchlist(line, [[^@@ -\v(\d+),?(\d*) \+(\d+),?(\d*)]]) - local line_stats = { - mod_count = tokens[3] == nil and 0 or tokens[3] == '' and 1 or tonumber(tokens[3]), - new_count = tokens[5] == nil and 0 or tokens[5] == '' and 1 or tonumber(tokens[5]), - } - - if line_stats.mod_count == 0 and line_stats.new_count > 0 then - added = added + line_stats.new_count - elseif line_stats.mod_count > 0 and line_stats.new_count == 0 then - removed = removed + line_stats.mod_count - else - local min = math.min(line_stats.mod_count, line_stats.new_count) - modified = modified + min - added = added + line_stats.new_count - min - removed = removed + line_stats.mod_count - min - end - end - end - Diff.git_diff = { added = added, modified = modified, removed = removed } -end - --- Updates the job args -function Diff.update_diff_args() - -- Donn't show git diff when current buffer doesn't have a filename - Diff.active_bufnr = tostring(vim.fn.bufnr()) - if #vim.fn.expand '%' == 0 then - Diff.diff_args = nil - Diff.git_diff = nil - return - end - Diff.diff_args = { - cmd = string.format( - [[git -C %s --no-pager diff --no-color --no-ext-diff -U0 -- %s]], - vim.fn.expand '%:h', - vim.fn.expand '%:t' - ), - on_stdout = function(_, data) - if next(data) then - Diff.diff_output_cache = vim.list_extend(Diff.diff_output_cache, data) - end - end, - on_stderr = function(_, data) - data = table.concat(data, '\n') - if #data > 1 or (#data == 1 and #data[1] > 0) then - Diff.git_diff = nil - Diff.diff_output_cache = {} - end - end, - on_exit = function() - if #Diff.diff_output_cache > 0 then - Diff.process_diff(Diff.diff_output_cache) - else - Diff.git_diff = { added = 0, modified = 0, removed = 0 } - end - diff_cache[vim.fn.bufnr()] = Diff.git_diff - end, - } - Diff.update_git_diff() -end - --- Update git_diff veriable -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 = modules.Job(Diff.diff_args) - if Diff.diff_job then - Diff.diff_job:start() - end - end -end - -return Diff diff --git a/lua/lualine/components/diff/git_diff.lua b/lua/lualine/components/diff/git_diff.lua new file mode 100644 index 0000000..8507aa0 --- /dev/null +++ b/lua/lualine/components/diff/git_diff.lua @@ -0,0 +1,135 @@ +local lualine_require = require 'lualine_require' +local modules = lualine_require.lazy_require { + utils = 'lualine.utils.utils', + Job = 'lualine.utils.job', +} + +local M = {} + +-- Vars +-- variable to store git diff stats +local git_diff = nil +-- accumulates output from diff process +local diff_output_cache = {} +-- variable to store git_diff job +local diff_job = nil + +local active_bufnr = '0' +local diff_cache = {} -- Stores last known value of diff of a buffer + +-- initialize the module +function M.init(opts) + if type(opts.source) == 'function' then + M.src = opts.source + else + modules.utils.define_autocmd('BufEnter', "lua require'lualine.components.diff.git_diff'.update_diff_args()") + modules.utils.define_autocmd('BufWritePost', "lua require'lualine.components.diff.git_diff'.update_git_diff()") + M.update_diff_args() + end +end + +-- Api to get git sign count +-- scheme : +-- { +-- added = added_count, +-- modified = modified_count, +-- removed = removed_count, +-- } +-- error_code = { added = -1, modified = -1, removed = -1 } +function M.get_sign_count(bufnr) + if bufnr then + return diff_cache[bufnr] + end + if M.src then + git_diff = M.src() + diff_cache[vim.fn.bufnr()] = git_diff + elseif vim.g.actual_curbuf ~= nil and active_bufnr ~= vim.g.actual_curbuf then + -- Workaround for https://github.com/hoob3rt/lualine.nvim/issues/286 + -- See upstream issue https://github.com/neovim/neovim/issues/15300 + -- Diff is out of sync re sync it. + M.update_diff_args() + end + return git_diff +end + +-- process diff data and update git_diff{ added, removed, modified } +local function process_diff(data) + -- Adapted from https://github.com/wbthomason/nvim-vcs.lua + local added, removed, modified = 0, 0, 0 + for _, line in ipairs(data) do + if string.find(line, [[^@@ ]]) then + local tokens = vim.fn.matchlist(line, [[^@@ -\v(\d+),?(\d*) \+(\d+),?(\d*)]]) + local line_stats = { + mod_count = tokens[3] == nil and 0 or tokens[3] == '' and 1 or tonumber(tokens[3]), + new_count = tokens[5] == nil and 0 or tokens[5] == '' and 1 or tonumber(tokens[5]), + } + + if line_stats.mod_count == 0 and line_stats.new_count > 0 then + added = added + line_stats.new_count + elseif line_stats.mod_count > 0 and line_stats.new_count == 0 then + removed = removed + line_stats.mod_count + else + local min = math.min(line_stats.mod_count, line_stats.new_count) + modified = modified + min + added = added + line_stats.new_count - min + removed = removed + line_stats.mod_count - min + end + end + end + git_diff = { added = added, modified = modified, removed = removed } +end + +-- Updates the job args +function M.update_diff_args() + -- Donn't show git diff when current buffer doesn't have a filename + active_bufnr = tostring(vim.fn.bufnr()) + if #vim.fn.expand '%' == 0 then + M.diff_args = nil + git_diff = nil + return + end + M.diff_args = { + cmd = string.format( + [[git -C %s --no-pager diff --no-color --no-ext-diff -U0 -- %s]], + vim.fn.expand '%:h', + vim.fn.expand '%:t' + ), + on_stdout = function(_, data) + if next(data) then + diff_output_cache = vim.list_extend(diff_output_cache, data) + end + end, + on_stderr = function(_, data) + data = table.concat(data, '\n') + if #data > 1 or (#data == 1 and #data[1] > 0) then + git_diff = nil + diff_output_cache = {} + end + end, + on_exit = function() + if #diff_output_cache > 0 then + process_diff(diff_output_cache) + else + git_diff = { added = 0, modified = 0, removed = 0 } + end + diff_cache[vim.fn.bufnr()] = git_diff + end, + } + M.update_git_diff() +end + +-- Update git_diff veriable +function M.update_git_diff() + if M.diff_args then + diff_output_cache = {} + if diff_job then + diff_job:stop() + end + diff_job = modules.Job(M.diff_args) + if diff_job then + diff_job:start() + end + end +end + +return M diff --git a/lua/lualine/components/diff/init.lua b/lua/lualine/components/diff/init.lua new file mode 100644 index 0000000..0e584d1 --- /dev/null +++ b/lua/lualine/components/diff/init.lua @@ -0,0 +1,88 @@ +-- Copyright (c) 2020-2021 shadmansaleh +-- MIT license, see LICENSE for more details. +local lualine_require = require 'lualine_require' +local modules = lualine_require.lazy_require { + git_diff = 'lualine.components.diff.git_diff', + utils = 'lualine.utils.utils', + utils_notices = 'lualine.utils.notices', + highlight = 'lualine.highlight', +} +local M = lualine_require.require('lualine.component'):extend() + +local default_options = { + colored = true, + symbols = { added = '+', modified = '~', removed = '-' }, + diff_color = { + added = { + fg = modules.utils.extract_highlight_colors('DiffAdd', 'fg') or '#f0e130', + }, + modified = { + fg = modules.utils.extract_highlight_colors('DiffChange', 'fg') or '#ff0038', + }, + removed = { + fg = modules.utils.extract_highlight_colors('DiffDelete', 'fg') or '#ff0038', + }, + }, +} + +-- Initializer +function M:init(options) + M.super.init(self, options) + self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options) + -- create highlights and save highlight_name in highlights table + if self.options.colored then + self.highlights = { + added = modules.highlight.create_component_highlight_group( + self.options.diff_color.added, + 'diff_added', + self.options + ), + modified = modules.highlight.create_component_highlight_group( + self.options.diff_color.modified, + 'diff_modified', + self.options + ), + removed = modules.highlight.create_component_highlight_group( + self.options.diff_color.removed, + 'diff_removed', + self.options + ), + } + end + modules.git_diff.init(self.options) +end + +-- Function that runs everytime statusline is updated +function M:update_status(is_focused) + local git_diff = modules.git_diff.get_sign_count((not is_focused and vim.fn.bufnr())) + if git_diff == nil then + return '' + end + + local colors = {} + if self.options.colored then + -- load the highlights and store them in colors table + for name, highlight_name in pairs(self.highlights) do + colors[name] = modules.highlight.component_format_highlight(highlight_name) + end + end + + local result = {} + -- loop though data and load available sections in result table + for _, name in ipairs { 'added', 'modified', 'removed' } do + if git_diff[name] and git_diff[name] > 0 then + if self.options.colored then + table.insert(result, colors[name] .. self.options.symbols[name] .. git_diff[name]) + else + table.insert(result, self.options.symbols[name] .. git_diff[name]) + end + end + end + if #result > 0 then + return table.concat(result, ' ') + else + return '' + end +end + +return M diff --git a/lua/lualine/components/encoding.lua b/lua/lualine/components/encoding.lua index a2f5fdd..f40aecc 100644 --- a/lua/lualine/components/encoding.lua +++ b/lua/lualine/components/encoding.lua @@ -1,9 +1,7 @@ -- Copyright (c) 2020-2021 hoob3rt -- MIT license, see LICENSE for more details. -local Encoding = require('lualine.component'):new() - -Encoding.update_status = function() +local function encoding() return [[%{strlen(&fenc)?&fenc:&enc}]] end -return Encoding +return encoding diff --git a/lua/lualine/components/fileformat.lua b/lua/lualine/components/fileformat.lua index a36d7ef..8ca764a 100644 --- a/lua/lualine/components/fileformat.lua +++ b/lua/lualine/components/fileformat.lua @@ -1,20 +1,20 @@ -- Copyright (c) 2020-2021 shadmansaleh -- MIT license, see LICENSE for more details. -local FileFormat = require('lualine.component'):new() +local M = require('lualine.component'):extend() -- stylua: ignore -FileFormat.icon = { +M.icon = { unix = '', -- e712 dos = '', -- e70f mac = '' -- e711 } -FileFormat.update_status = function(self) +M.update_status = function(self) if self.options.icons_enabled and not self.options.icon then local format = vim.bo.fileformat - return FileFormat.icon[format] or format + return M.icon[format] or format end return vim.bo.fileformat end -return FileFormat +return M diff --git a/lua/lualine/components/filename.lua b/lua/lualine/components/filename.lua index 2f4f6f3..27346d2 100644 --- a/lua/lualine/components/filename.lua +++ b/lua/lualine/components/filename.lua @@ -1,6 +1,6 @@ -- Copyright (c) 2020-2021 shadmansaleh -- MIT license, see LICENSE for more details. -local FileName = require('lualine.component'):new() +local M = require('lualine.component'):extend() local default_options = { symbols = { modified = '[+]', readonly = '[-]' }, @@ -18,13 +18,12 @@ local function shorten_path(path, sep) return path:gsub(string.format('([^%s])[^%s]+%%%s', sep, sep, sep), '%1' .. sep, 1) end -FileName.new = function(self, options, child) - local new_instance = self._parent:new(options, child or FileName) - new_instance.options = vim.tbl_deep_extend('keep', new_instance.options or {}, default_options) - return new_instance +M.init = function(self, options) + M.super.init(self, options) + self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options) end -FileName.update_status = function(self) +M.update_status = function(self) local data if self.options.path == 1 then -- relative path @@ -63,4 +62,4 @@ FileName.update_status = function(self) return data end -return FileName +return M diff --git a/lua/lualine/components/filesize.lua b/lua/lualine/components/filesize.lua index 523dda2..cc95da8 100644 --- a/lua/lualine/components/filesize.lua +++ b/lua/lualine/components/filesize.lua @@ -1,8 +1,6 @@ -- Copyright (c) 2020-2021 shadmansaleh -- MIT license, see LICENSE for more details. -local M = require('lualine.component'):new() - -M.update_status = function() +local function filesize() local file = vim.fn.expand '%:p' if file == nil or #file == 0 then return '' @@ -24,4 +22,4 @@ M.update_status = function() return string.format('%.1f%s', size, sufixes[i]) end -return M +return filesize diff --git a/lua/lualine/components/filetype.lua b/lua/lualine/components/filetype.lua index fac7c57..89b74d2 100644 --- a/lua/lualine/components/filetype.lua +++ b/lua/lualine/components/filetype.lua @@ -5,46 +5,23 @@ local modules = lualine_require.lazy_require { highlight = 'lualine.highlight', utils = 'lualine.utils.utils', } -local FileType = lualine_require.require('lualine.component'):new() - -local function check_deprecated_options(options) - local function rename_notice(before, now) - if options[before] then - require('lualine.utils.notices').add_notice(string.format( - [[ -### option.%s -%s option has been renamed to `%s`. Please use `%s` instead in your config -for filetype component. -]], - before, - before, - now, - now - )) - options[now] = options[before] - options[before] = nil - end - end - rename_notice('disable_text', 'icon_only') -end +local M = lualine_require.require('lualine.component'):extend() local default_options = { colored = true, icon_only = false, } -function FileType:new(options, child) - local new_instance = self._parent:new(options, child or FileType) - new_instance.options = vim.tbl_deep_extend('keep', new_instance.options or {}, default_options) - check_deprecated_options(new_instance.options) - return new_instance +function M:init(options) + M.super.init(self, options) + self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options) end -function FileType.update_status() +function M.update_status() return vim.bo.filetype or '' end -function FileType:apply_icon() +function M:apply_icon() if not self.options.icons_enabled then return end @@ -87,4 +64,4 @@ function FileType:apply_icon() end end -return FileType +return M diff --git a/lua/lualine/components/hostname.lua b/lua/lualine/components/hostname.lua index 5ac4112..9c43b14 100644 --- a/lua/lualine/components/hostname.lua +++ b/lua/lualine/components/hostname.lua @@ -1,7 +1,7 @@ -- Copyright (c) 2020-2021 hoob3rt -- MIT license, see LICENSE for more details. -local HostName = require('lualine.component'):new() +local function hostname() + return vim.loop.os_gethostname() +end -HostName.update_status = vim.loop.os_gethostname - -return HostName +return hostname diff --git a/lua/lualine/components/location.lua b/lua/lualine/components/location.lua index 39b2eae..1ffff54 100644 --- a/lua/lualine/components/location.lua +++ b/lua/lualine/components/location.lua @@ -1,9 +1,7 @@ -- Copyright (c) 2020-2021 hoob3rt -- MIT license, see LICENSE for more details. -local Location = require('lualine.component'):new() - -Location.update_status = function() +local function location() return [[%3l:%-2c]] end -return Location +return location diff --git a/lua/lualine/components/mode.lua b/lua/lualine/components/mode.lua index cec8222..721d6ca 100644 --- a/lua/lualine/components/mode.lua +++ b/lua/lualine/components/mode.lua @@ -1,9 +1,4 @@ -- 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 - -Mode.update_status = get_mode - -return Mode +return get_mode diff --git a/lua/lualine/components/progress.lua b/lua/lualine/components/progress.lua index ac7e52f..e4a7054 100644 --- a/lua/lualine/components/progress.lua +++ b/lua/lualine/components/progress.lua @@ -1,9 +1,7 @@ -- Copyright (c) 2020-2021 hoob3rt -- MIT license, see LICENSE for more details. -local Progress = require('lualine.component'):new() - -Progress.update_status = function() +local function progress() return [[%3P]] end -return Progress +return progress diff --git a/lua/lualine/components/special/eval_func_component.lua b/lua/lualine/components/special/eval_func_component.lua index 4656b89..94253e3 100644 --- a/lua/lualine/components/special/eval_func_component.lua +++ b/lua/lualine/components/special/eval_func_component.lua @@ -1,36 +1,35 @@ -- Copyright (c) 2020-2021 shadmansaleh -- MIT license, see LICENSE for more details. +local M = require('lualine.component'):extend() -local EvalFuncComponent = require('lualine.component'):new() - -EvalFuncComponent.update_status = function(self) +function M:update_status() local component = self.options[1] local ok, status if self.options.type == nil then - ok, status = pcall(EvalFuncComponent.lua_eval, component) + ok, status = pcall(M.lua_eval, component) if not ok then - status = EvalFuncComponent.vim_function(component) + status = M.vim_function(component) end else - if self.options.type == 'luae' then - ok, status = pcall(EvalFuncComponent.lua_eval, component) + if self.options.type == 'lua_expr' then + ok, status = pcall(M.lua_eval, component) if not ok then status = nil end - elseif self.options.type == 'vimf' then - status = EvalFuncComponent.vim_function(component) + elseif self.options.type == 'vim_fun' then + status = M.vim_function(component) end end return status end -EvalFuncComponent.lua_eval = function(code) +function M.lua_eval(code) local result = loadstring('return ' .. code)() assert(result, 'String expected got nil') return tostring(result) end -EvalFuncComponent.vim_function = function(name) +function M.vim_function(name) -- vim function component local ok, return_val = pcall(vim.api.nvim_call_function, name, {}) if not ok then @@ -40,4 +39,4 @@ EvalFuncComponent.vim_function = function(name) return ok and return_val or '' end -return EvalFuncComponent +return M diff --git a/lua/lualine/components/special/function_component.lua b/lua/lualine/components/special/function_component.lua index b360c31..4856dad 100644 --- a/lua/lualine/components/special/function_component.lua +++ b/lua/lualine/components/special/function_component.lua @@ -1,8 +1,8 @@ -- Copyright (c) 2020-2021 shadmansaleh -- MIT license, see LICENSE for more details. -local FunctionComponent = require('lualine.component'):new() +local M = require('lualine.component'):extend() -FunctionComponent.update_status = function(self, is_focused) +M.update_status = function(self, is_focused) -- 1st element in options table is the function provided by config local ok, retval ok, retval = pcall(self.options[1], self, is_focused) @@ -18,4 +18,4 @@ FunctionComponent.update_status = function(self, is_focused) return retval end -return FunctionComponent +return M diff --git a/lua/lualine/components/special/vim_var_component.lua b/lua/lualine/components/special/vim_var_component.lua index eb46b28..f6853a2 100644 --- a/lua/lualine/components/special/vim_var_component.lua +++ b/lua/lualine/components/special/vim_var_component.lua @@ -1,7 +1,8 @@ -- Copyright (c) 2020-2021 shadmansaleh -- MIT license, see LICENSE for more details. -local VarComponent = require('lualine.component'):new() -VarComponent.update_status = function(self) +local M = require('lualine.component'):extend() + +function M:update_status() local component = self.options[1] -- vim veriable component -- accepts g:, v:, t:, w:, b:, o, go:, vo:, to:, wo:, bo: @@ -31,4 +32,4 @@ VarComponent.update_status = function(self) return ok and return_val or '' end -return VarComponent +return M diff --git a/lua/lualine/components/tabs.lua b/lua/lualine/components/tabs.lua deleted file mode 100644 index c55b72e..0000000 --- a/lua/lualine/components/tabs.lua +++ /dev/null @@ -1,217 +0,0 @@ --- Copyright (c) 2020-2021 shadmansaleh --- MIT license, see LICENSE for more details. -local Tabs = require('lualine.component'):new() -local highlight = require 'lualine.highlight' - -local default_options = { - max_length = 0, - mode = 0, - tabs_color = { - active = nil, - inactive = nil, - }, -} - -local function get_hl(section, is_active) - local suffix = is_active and '_normal' or '_inactive' - local section_redirects = { - lualine_x = 'lualine_c', - lualine_y = 'lualine_b', - lualine_z = 'lualine_a', - } - if section_redirects[section] then - section = highlight.highlight_exists(section .. suffix) and section or section_redirects[section] - end - return section .. suffix -end - -local Tab = {} - -function Tab:new(tab) - assert(tab.tabnr, 'Cannot create Tab without tabnr') - local newObj = { - tabnr = tab.tabnr, - options = tab.options, - highlights = tab.highlights, - } - self.__index = self - newObj = setmetatable(newObj, self) - return newObj -end - -function Tab:label() - local buflist = vim.fn.tabpagebuflist(self.tabnr) - local winnr = vim.fn.tabpagewinnr(self.tabnr) - local bufnr = buflist[winnr] - local file = vim.fn.bufname(bufnr) - local buftype = vim.fn.getbufvar(bufnr, '&buftype') - if buftype == 'help' then - return 'help:' .. vim.fn.fnamemodify(file, ':t:r') - elseif buftype == 'terminal' then - local match = string.match(vim.split(file, ' ')[1], 'term:.*:(%a+)') - return match ~= nil and match or vim.fn.fnamemodify(vim.env.SHELL, ':t') - elseif vim.fn.isdirectory(file) == 1 then - return vim.fn.fnamemodify(file, ':p:.') - elseif file == '' then - return '[No Name]' - end - return vim.fn.fnamemodify(file, ':t') -end - -function Tab:render() - local name - if self.ellipse then - name = '...' - else - if self.options.mode == 0 then - name = string.format('%s%s ', (self.last or not self.first) and ' ' or '', tostring(self.tabnr)) - elseif self.options.mode == 1 then - name = string.format('%s%s ', (self.last or not self.first) and ' ' or '', self:label()) - else - name = string.format('%s%s %s ', (self.last or not self.first) and ' ' or '', tostring(self.tabnr), self:label()) - end - end - self.len = #name - local line = string.format('%%%s@LualineSwitchTab@%s%%T', self.tabnr, name) - line = highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')]) .. line - - if self.options.self.section < 'lualine_x' and not self.first then - local sep_before = self:separator_before() - line = sep_before .. line - self.len = self.len + vim.fn.strchars(sep_before) - elseif self.options.self.section >= 'lualine_x' and not self.last then - local sep_after = self:separator_after() - line = line .. sep_after - self.len = self.len + vim.fn.strchars(sep_after) - end - return line -end - -function Tab:separator_before() - if self.current or self.aftercurrent then - return '%S{' .. self.options.section_separators.left .. '}' - else - return self.options.component_separators.left - end -end - -function Tab:separator_after() - if self.current or self.beforecurrent then - return '%s{' .. self.options.section_separators.right .. '}' - else - return self.options.component_separators.right - end -end - -function Tabs:new(options, child) - local newObj = self._parent:new(options, child or Tabs) - default_options.tabs_color = { - active = get_hl(options.self.section, true), - inactive = get_hl(options.self.section, false), - } - newObj.options = vim.tbl_deep_extend('keep', newObj.options or {}, default_options) - -- stylua: ignore - newObj.highlights = { - active = highlight.create_component_highlight_group( - newObj.options.tabs_color.active, - 'tabs_active', - newObj.options - ), - inactive = highlight.create_component_highlight_group( - newObj.options.tabs_color.inactive, - 'tabs_active', - newObj.options - ), - } - return newObj -end - -function Tabs:update_status() - local data = {} - local tabs = {} - for t = 1, vim.fn.tabpagenr '$' do - tabs[#tabs + 1] = Tab:new { tabnr = t, options = self.options, highlights = self.highlights } - end - local current = vim.fn.tabpagenr() - tabs[1].first = true - tabs[#tabs].last = true - if tabs[current] then - tabs[current].current = true - end - if tabs[current - 1] then - tabs[current - 1].beforecurrent = true - end - if tabs[current + 1] then - tabs[current + 1].aftercurrent = true - end - - local max_length = self.options.max_length - if max_length == 0 then - max_length = math.floor(vim.o.columns / 3) - end - local total_length - for i, tab in pairs(tabs) do - if tab.current then - current = i - end - end - local current_tab = tabs[current] - if current_tab == nil then - local t = Tab:new { tabnr = vim.fn.tabpagenr(), options = self.options, highlights = self.highlights } - t.current = true - t.last = true - data[#data + 1] = t:render() - else - data[#data + 1] = current_tab:render() - total_length = current_tab.len - local i = 0 - local before, after - while true do - i = i + 1 - before = tabs[current - i] - after = tabs[current + i] - local rendered_before, rendered_after - if before == nil and after == nil then - break - end - if before then - rendered_before = before:render() - total_length = total_length + before.len - if total_length > max_length then - break - end - table.insert(data, 1, rendered_before) - end - if after then - rendered_after = after:render() - total_length = total_length + after.len - if total_length > max_length then - break - end - data[#data + 1] = rendered_after - end - end - if total_length > max_length then - if before ~= nil then - before.ellipse = true - before.first = true - table.insert(data, 1, before:render()) - end - if after ~= nil then - after.ellipse = true - after.last = true - data[#data + 1] = after:render() - end - end - end - - return table.concat(data) -end - -vim.cmd [[ - function! LualineSwitchTab(tabnr, mouseclicks, mousebutton, modifiers) - execute a:tabnr . "tabnext" - endfunction -]] - -return Tabs diff --git a/lua/lualine/components/tabs/init.lua b/lua/lualine/components/tabs/init.lua new file mode 100644 index 0000000..6a521ef --- /dev/null +++ b/lua/lualine/components/tabs/init.lua @@ -0,0 +1,140 @@ +-- Copyright (c) 2020-2021 shadmansaleh +-- MIT license, see LICENSE for more details. +local require = require('lualine_require').require +local Tab = require 'lualine.components.tabs.tab' +local M = require('lualine.component'):extend() +local highlight = require 'lualine.highlight' + +local default_options = { + max_length = 0, + mode = 0, + tabs_color = { + active = nil, + inactive = nil, + }, +} + +local function get_hl(section, is_active) + local suffix = is_active and '_normal' or '_inactive' + local section_redirects = { + lualine_x = 'lualine_c', + lualine_y = 'lualine_b', + lualine_z = 'lualine_a', + } + if section_redirects[section] then + section = highlight.highlight_exists(section .. suffix) and section or section_redirects[section] + end + return section .. suffix +end + +function M:init(options) + M.super.init(self, options) + default_options.tabs_color = { + active = get_hl(options.self.section, true), + inactive = get_hl(options.self.section, false), + } + self.options = vim.tbl_deep_extend('keep', self.options or {}, default_options) + -- stylua: ignore + self.highlights = { + active = highlight.create_component_highlight_group( + self.options.tabs_color.active, + 'tabs_active', + self.options + ), + inactive = highlight.create_component_highlight_group( + self.options.tabs_color.inactive, + 'tabs_active', + self.options + ), + } +end + +function M:update_status() + local data = {} + local tabs = {} + for t = 1, vim.fn.tabpagenr '$' do + tabs[#tabs + 1] = Tab { tabnr = t, options = self.options, highlights = self.highlights } + end + local current = vim.fn.tabpagenr() + tabs[1].first = true + tabs[#tabs].last = true + if tabs[current] then + tabs[current].current = true + end + if tabs[current - 1] then + tabs[current - 1].beforecurrent = true + end + if tabs[current + 1] then + tabs[current + 1].aftercurrent = true + end + + local max_length = self.options.max_length + if max_length == 0 then + max_length = math.floor(vim.o.columns / 3) + end + local total_length + for i, tab in pairs(tabs) do + if tab.current then + current = i + end + end + local current_tab = tabs[current] + if current_tab == nil then + local t = Tab { tabnr = vim.fn.tabpagenr(), options = self.options, highlights = self.highlights } + t.current = true + t.last = true + data[#data + 1] = t:render() + else + data[#data + 1] = current_tab:render() + total_length = current_tab.len + local i = 0 + local before, after + while true do + i = i + 1 + before = tabs[current - i] + after = tabs[current + i] + local rendered_before, rendered_after + if before == nil and after == nil then + break + end + if before then + rendered_before = before:render() + total_length = total_length + before.len + if total_length > max_length then + break + end + table.insert(data, 1, rendered_before) + end + if after then + rendered_after = after:render() + total_length = total_length + after.len + if total_length > max_length then + break + end + data[#data + 1] = rendered_after + end + end + if total_length > max_length then + if before ~= nil then + before.ellipse = true + before.first = true + table.insert(data, 1, before:render()) + end + if after ~= nil then + after.ellipse = true + after.last = true + data[#data + 1] = after:render() + end + end + end + + return table.concat(data) +end + +vim.cmd [[ + function! LualineSwitchTab(tabnr, mouseclicks, mousebutton, modifiers) + execute a:tabnr . "tabnext" + endfunction +]] + +return M diff --git a/lua/lualine/components/tabs/tab.lua b/lua/lualine/components/tabs/tab.lua new file mode 100644 index 0000000..70d1c89 --- /dev/null +++ b/lua/lualine/components/tabs/tab.lua @@ -0,0 +1,75 @@ +local highlight = require 'lualine.highlight' +local Tab = require('lualine.utils.class'):extend() + +function Tab:init(opts) + assert(opts.tabnr, 'Cannot create Tab without tabnr') + self.tabnr = opts.tabnr + self.options = opts.options + self.highlights = opts.highlights +end + +function Tab:label() + local buflist = vim.fn.tabpagebuflist(self.tabnr) + local winnr = vim.fn.tabpagewinnr(self.tabnr) + local bufnr = buflist[winnr] + local file = vim.fn.bufname(bufnr) + local buftype = vim.fn.getbufvar(bufnr, '&buftype') + if buftype == 'help' then + return 'help:' .. vim.fn.fnamemodify(file, ':t:r') + elseif buftype == 'terminal' then + local match = string.match(vim.split(file, ' ')[1], 'term:.*:(%a+)') + return match ~= nil and match or vim.fn.fnamemodify(vim.env.SHELL, ':t') + elseif vim.fn.isdirectory(file) == 1 then + return vim.fn.fnamemodify(file, ':p:.') + elseif file == '' then + return '[No Name]' + end + return vim.fn.fnamemodify(file, ':t') +end + +function Tab:render() + local name + if self.ellipse then + name = '...' + else + if self.options.mode == 0 then + name = string.format('%s%s ', (self.last or not self.first) and ' ' or '', tostring(self.tabnr)) + elseif self.options.mode == 1 then + name = string.format('%s%s ', (self.last or not self.first) and ' ' or '', self:label()) + else + name = string.format('%s%s %s ', (self.last or not self.first) and ' ' or '', tostring(self.tabnr), self:label()) + end + end + self.len = #name + local line = string.format('%%%s@LualineSwitchTab@%s%%T', self.tabnr, name) + line = highlight.component_format_highlight(self.highlights[(self.current and 'active' or 'inactive')]) .. line + + if self.options.self.section < 'lualine_x' and not self.first then + local sep_before = self:separator_before() + line = sep_before .. line + self.len = self.len + vim.fn.strchars(sep_before) + elseif self.options.self.section >= 'lualine_x' and not self.last then + local sep_after = self:separator_after() + line = line .. sep_after + self.len = self.len + vim.fn.strchars(sep_after) + end + return line +end + +function Tab:separator_before() + if self.current or self.aftercurrent then + return '%S{' .. self.options.section_separators.left .. '}' + else + return self.options.component_separators.left + end +end + +function Tab:separator_after() + if self.current or self.beforecurrent then + return '%s{' .. self.options.section_separators.right .. '}' + else + return self.options.component_separators.right + end +end + +return Tab diff --git a/lua/lualine/config.lua b/lua/lualine/config.lua index a09cfba..ae5527e 100644 --- a/lua/lualine/config.lua +++ b/lua/lualine/config.lua @@ -29,25 +29,11 @@ local config = { extensions = {}, } -local function check_sep_format_deprecation(sep) - if type(sep) == 'table' and vim.tbl_islist(sep) then - require('lualine.utils.notices').add_persistent_notice(string.format [[ -### option.separator -Using list for configuring separators has been deprecated. Please configure it -with {left = left_sep, right = right_sep} like table. -]]) - sep = { left = sep[1], right = sep[2] or sep[1] } - end - return sep -end - -- change separator format 'x' to {left='x', right='x'} local function fix_separators(separators) if separators ~= nil then if type(separators) == 'string' then return { left = separators, right = separators } - else - return check_sep_format_deprecation(separators) end end return separators diff --git a/lua/lualine/utils/class.lua b/lua/lualine/utils/class.lua new file mode 100644 index 0000000..83700fc --- /dev/null +++ b/lua/lualine/utils/class.lua @@ -0,0 +1,43 @@ +-- Adapted from https://github.com/rxi/classic/blob/master/classic.lua +local Object = {} + +Object.__index = Object + +-- luacheck: push no unused args +-- Initializer +function Object:init(...) end +-- luacheck: pop + +-- Extened base class to create a child class +function Object:extend() + local cls = {} + for k, v in pairs(self) do + if k:find '__' == 1 then + cls[k] = v + end + end + cls.__index = cls + cls.super = self + setmetatable(cls, self) + return cls +end + +-- luacheck: push no unused args +function Object:__tostring() + return 'Object' +end +-- luacheck: pop + +-- Creates a new object +function Object:new(...) + local obj = setmetatable({}, self) + obj:init(...) + return obj +end + +-- Creates a new object +function Object:__call(...) + return self:new(...) +end + +return Object diff --git a/lua/lualine/utils/loader.lua b/lua/lualine/utils/loader.lua index d8e5547..ef79d13 100644 --- a/lua/lualine/utils/loader.lua +++ b/lua/lualine/utils/loader.lua @@ -11,14 +11,19 @@ local is_valid_filename = lualine_require.is_valid_filename local sep = lualine_require.sep local component_types = { - luaf = function(component) - return require('lualine.components.special.function_component'):new(component) + lua_fun = function(component) + return require 'lualine.components.special.function_component'(component) end, mod = function(component) local ok, loaded_component = pcall(require, 'lualine.components.' .. component[1]) if ok then component.component_name = component[1] - loaded_component = loaded_component:new(component) + if type(loaded_component) == 'table' then + loaded_component = loaded_component(component) + elseif type(loaded_component) == 'function' then + component[1] = loaded_component + loaded_component = require 'lualine.components.special.function_component'(component) + end return loaded_component end end, @@ -27,26 +32,26 @@ local component_types = { component[1] = function() return stl_expr end - return require('lualine.components.special.function_component'):new(component) + return require 'lualine.components.special.function_component'(component) end, var = function(component) - return require('lualine.components.special.vim_var_component'):new(component) + return require 'lualine.components.special.vim_var_component'(component) end, ['_'] = function(component) - return require('lualine.components.special.eval_func_component'):new(component) + return require 'lualine.components.special.eval_func_component'(component) end, } local function component_loader(component) if type(component[1]) == 'function' then - return component_types.luaf(component) + return component_types.lua_fun(component) end if type(component[1]) == 'string' then -- load the component if component.type ~= nil then - if component_types[component.type] and component.type ~= 'luaf' then + if component_types[component.type] and component.type ~= 'lua_fun' then return component_types[component.type](component) - elseif component.type == 'vimf' or component.type == 'luae' then + elseif component.type == 'vim_fun' or component.type == 'lua_expr' then return component_types['_'](component) else modules.notice.add_notice(string.format( @@ -73,85 +78,39 @@ end local function option_deprecatation_notice(component) local types = { - case = function() - local kind = component.upper ~= nil and 'upper' or 'lower' + type_name = function() + local changed_to = component.type == 'luae' and 'lua_expr' or 'vim_fun' modules.notice.add_notice(string.format( [[ -### option.%s +### option.type.%s -Option `%s` has been deprecated. -Please use `fmt` option if you need to change case of a component. +type name `%s` has been deprecated. +Please use `%s`. -You have some thing like this in your config: +You have some thing like this in your config config for %s component: ```lua - %s = true, + type = %s, ``` You'll have to change it to this to retain old behavior: ```lua - fmt = string.%s + type = %s ``` ]], - kind, - kind, - kind, - kind + component.type, + component.type, + changed_to, + tostring(component[1]), + component.type, + changed_to )) - end, - padding = function() - local kind = component.left_padding ~= nil and 'left_padding' or 'right_padding' - modules.notice.add_notice(string.format( - [[ -### option.%s - -Option `%s` has been deprecated. -Please use `padding` option to set left/right padding. - -You have some thing like this in your config: - -```lua - %s = %d, -``` - -You'll have to change it to this to retain old behavior: - -```lua - padding = { %s = %d } -``` -if you've set both left_padding and right_padding for a component -you'll need to have something like -```lua - padding = { left = x, right = y } -``` -When you set `padding = x` it's same as `padding = {left = x, right = x}` -]], - kind, - kind, - kind, - component[kind], - kind == 'left_padding' and 'left' or 'right', - component[kind] - )) - if component.left_padding and component.right_padding then - component.padding = { left = component.left_padding, right = component.right_padding } - component.left_padding = nil - component.right_padding = nil - elseif component.left_padding then - component.padding = { left = component.left_padding, right = 1 } - component.left_padding = nil - else - component.padding = { left = 1, right = component.right_padding } - component.right_padding = nil - end + component.type = changed_to end, } - if component.upper ~= nil or component.lower ~= nil then - types.case() - end - if component.left_padding ~= nil or component.right_padding ~= nil then - types.padding() + if component.type == 'luae' or component.type == 'vimf' then + types.type_name() end end @@ -226,6 +185,10 @@ local function load_theme(theme_name) local retval local path = table.concat { 'lua/lualine/themes/', theme_name, '.lua' } local files = vim.api.nvim_get_runtime_file(path, true) + if #files <= 0 then + path = table.concat { 'lua/lualine/themes/', theme_name, '/init.lua' } + files = vim.api.nvim_get_runtime_file(path, true) + end local n_files = #files if n_files == 0 then -- No match found diff --git a/lua/lualine_require.lua b/lua/lualine_require.lua index 6aa35f7..6126104 100644 --- a/lua/lualine_require.lua +++ b/lua/lualine_require.lua @@ -24,19 +24,34 @@ function M.require(module) if package.loaded[module] then return package.loaded[module] end - local pattern = module:gsub('%.', M.sep) .. '.lua' + local pattern_dir = module:gsub('%.', M.sep) + local pattern_path = pattern_dir .. '.lua' if M.plugin_dir then - local path = M.plugin_dir .. pattern + local path = M.plugin_dir .. pattern_path assert(M.is_valid_filename(module), 'Invalid filename') - if vim.loop.fs_stat(path) then + local file_stat, dir_stat + file_stat = vim.loop.fs_stat(path) + if not file_stat then + path = M.plugin_dir .. pattern_dir + dir_stat = vim.loop.fs_stat(path) + if dir_stat and dir_stat.type == 'directory' then + path = path .. M.sep .. 'init.lua' + file_stat = vim.loop.fs_stat(path) + end + end + if file_stat and file_stat.type == 'file' then local mod_result = dofile(path) package.loaded[module] = mod_result return mod_result end end - pattern = table.concat { 'lua/', module:gsub('%.', '/'), '.lua' } - local paths = vim.api.nvim_get_runtime_file(pattern, false) + pattern_path = table.concat { 'lua/', module:gsub('%.', '/'), '.lua' } + local paths = vim.api.nvim_get_runtime_file(pattern_path, false) + if #paths <= 0 then + pattern_path = table.concat { 'lua/', module:gsub('%.', '/'), '/init.lua' } + paths = vim.api.nvim_get_runtime_file(pattern_path, false) + end if #paths > 0 then local mod_result = dofile(paths[1]) package.loaded[module] = mod_result diff --git a/lua/tests/helpers.lua b/lua/tests/helpers.lua index 1f46144..74e1b86 100644 --- a/lua/tests/helpers.lua +++ b/lua/tests/helpers.lua @@ -16,8 +16,16 @@ M.assert_component = function(component, opts, result) -- for testing global options if component == nil then component = 'special.function_component' + else + opts.component_name = component + end + local comp = require('lualine.components.' .. component) + if type(comp) == 'table' then + comp = comp(opts) + elseif type(comp) == 'function' then + opts[1] = comp + comp = require 'lualine.components.special.function_component'(opts) end - local comp = require('lualine.components.' .. component):new(opts) eq(result, comp:draw(opts.hl)) end diff --git a/lua/tests/spec/component_spec.lua b/lua/tests/spec/component_spec.lua index 5e02586..5d616cc 100644 --- a/lua/tests/spec/component_spec.lua +++ b/lua/tests/spec/component_spec.lua @@ -12,20 +12,20 @@ local stub = require 'luassert.stub' describe('Component:', function() it('can select separators', function() local opts = build_component_opts() - local comp = require('lualine.components.special.function_component'):new(opts) + local comp = require 'lualine.components.special.function_component'(opts) -- correct for lualine_c eq('', comp.options.separator) local opts2 = build_component_opts { self = { section = 'lualine_y' } } - local comp2 = require('lualine.components.special.function_component'):new(opts2) + local comp2 = require 'lualine.components.special.function_component'(opts2) -- correct for lualine_u eq('', comp2.options.separator) end) it('can provide unique identifier', function() local opts1 = build_component_opts() - local comp1 = require('lualine.components.special.function_component'):new(opts1) + local comp1 = require 'lualine.components.special.function_component'(opts1) local opts2 = build_component_opts() - local comp2 = require('lualine.components.special.function_component'):new(opts2) + local comp2 = require 'lualine.components.special.function_component'(opts2) neq(comp1.component_no, comp2.component_no) end) @@ -35,7 +35,7 @@ describe('Component:', function() local hl = require 'lualine.highlight' stub(hl, 'create_component_highlight_group') hl.create_component_highlight_group.returns 'MyCompHl' - local comp1 = require('lualine.components.special.function_component'):new(opts1) + local comp1 = require 'lualine.components.special.function_component'(opts1) eq('MyCompHl', comp1.options.color_highlight) -- color highlight wan't in options when create_comp_hl was -- called so remove it before assert @@ -46,7 +46,7 @@ describe('Component:', function() local opts2 = build_component_opts { color = color } stub(hl, 'create_component_highlight_group') hl.create_component_highlight_group.returns 'MyCompLinkedHl' - local comp2 = require('lualine.components.special.function_component'):new(opts2) + local comp2 = require 'lualine.components.special.function_component'(opts2) eq('MyCompLinkedHl', comp2.options.color_highlight) -- color highlight wan't in options when create_comp_hl was -- called so remove it before assert @@ -90,27 +90,6 @@ describe('Component:', function() end) describe('Global options:', function() - it('upper', function() - local opts = build_component_opts { - component_separators = { left = '', right = '' }, - padding = 0, - upper = true, - } - assert_component(nil, opts, 'TEST') - end) - - it('lower', function() - local opts = build_component_opts { - function() - return 'TeSt' - end, - component_separators = { left = '', right = '' }, - padding = 0, - lower = true, - } - assert_component(nil, opts, 'test') - end) - it('left_padding', function() local opts = build_component_opts { component_separators = { left = '', right = '' }, @@ -206,7 +185,7 @@ describe('Component:', function() padding = 0, color = 'MyHl', } - local comp = require('lualine.components.special.function_component'):new(opts) + local comp = require 'lualine.components.special.function_component'(opts) local custom_link_hl_name = 'lualine_' .. comp.options.component_name .. '_no_mode' eq('%#' .. custom_link_hl_name .. '#test', comp:draw(opts.hl)) local opts2 = build_component_opts { @@ -217,7 +196,7 @@ describe('Component:', function() local hl = require 'lualine.highlight' stub(hl, 'component_format_highlight') hl.component_format_highlight.returns '%#MyCompHl#' - local comp2 = require('lualine.components.special.function_component'):new(opts2) + local comp2 = require 'lualine.components.special.function_component'(opts2) assert_component(nil, opts2, '%#MyCompHl#test') assert.stub(hl.component_format_highlight).was_called_with(comp2.options.color_highlight) hl.component_format_highlight:revert() diff --git a/lua/tests/spec/config_spec.lua b/lua/tests/spec/config_spec.lua index 484e6d7..df5d48c 100644 --- a/lua/tests/spec/config_spec.lua +++ b/lua/tests/spec/config_spec.lua @@ -63,11 +63,14 @@ describe('config parsing', function() end) it('table', function() local config = { - options = { component_separators = { 'a' }, section_separators = { 'b' } }, + options = { + component_separators = { left = 'a', right = 'b' }, + section_separators = { left = 'b', right = 'a' }, + }, } config = config_module.apply_configuration(config) - eq(config.options.component_separators, { left = 'a', right = 'a' }) - eq(config.options.section_separators, { left = 'b', right = 'b' }) + eq(config.options.component_separators, { left = 'a', right = 'b' }) + eq(config.options.section_separators, { left = 'b', right = 'a' }) end) end) it('no seprarators', function() diff --git a/lua/tests/spec/utils_spec.lua b/lua/tests/spec/utils_spec.lua index ced2a16..5f4e9ef 100644 --- a/lua/tests/spec/utils_spec.lua +++ b/lua/tests/spec/utils_spec.lua @@ -59,8 +59,8 @@ describe('Section genarator', function() it('can draw', function() local opts = build_component_opts { section_separators = { left = '', right = '' } } local section = { - require('lualine.components.special.function_component'):new(opts), - require('lualine.components.special.function_component'):new(opts), + require 'lualine.components.special.function_component'(opts), + require 'lualine.components.special.function_component'(opts), } eq('%#lualine_MySection_normal# test %#lualine_MySection_normal# test ', sec.draw_section(section, 'MySection')) end) @@ -78,9 +78,9 @@ describe('Section genarator', function() } require('lualine.highlight').create_highlight_groups(require 'lualine.themes.gruvbox') local section = { - require('lualine.components.special.function_component'):new(opts), - require('lualine.components.special.function_component'):new(opts_colored), - require('lualine.components.special.function_component'):new(opts), + require 'lualine.components.special.function_component'(opts), + require 'lualine.components.special.function_component'(opts_colored), + require 'lualine.components.special.function_component'(opts), } local highlight_name2 = 'lualine_' .. section[2].options.component_name .. '_no_mode' -- Removes separator on string color @@ -88,14 +88,14 @@ describe('Section genarator', function() '%#lualine_MySection_normal# test %#' .. highlight_name2 .. '#' .. ' test %#lualine_MySection_normal# test ', sec.draw_section(section, 'MySection') ) - section[2] = require('lua.lualine.components.special.function_component'):new(opts_colored2) + section[2] = require 'lua.lualine.components.special.function_component'(opts_colored2) local highlight_name = '%#lualine_c_' .. section[2].options.component_name .. '_normal#' -- Removes separator on color with bg eq( '%#lualine_MySection_normal# test ' .. highlight_name .. ' test %#lualine_MySection_normal# test ', sec.draw_section(section, 'MySection') ) - section[2] = require('lua.lualine.components.special.function_component'):new(opts_colored3) + section[2] = require 'lua.lualine.components.special.function_component'(opts_colored3) highlight_name2 = '%#lualine_c_' .. section[2].options.component_name .. '_normal#' -- Doesn't remove separator on color without bg eq(