From 0ac721d37637ab1903b66822fd1a1ee9d08013f0 Mon Sep 17 00:00:00 2001 From: Shadman <13149513+shadmansaleh@users.noreply.github.com> Date: Wed, 20 Jul 2022 19:28:49 +0600 Subject: [PATCH] feat: add on_click option to interact with mouse (#742) * feat: add on_click option to interact with mouse closes #706 --- README.md | 5 ++++ doc/lualine.txt | 5 ++++ lua/lualine/component.lua | 48 +++++++++++++++++++++++++++++----- lua/lualine/utils/fn_store.lua | 38 +++++++++++++++++++++++++++ lua/lualine/utils/loader.lua | 4 ++- 5 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 lua/lualine/utils/fn_store.lua diff --git a/README.md b/README.md index 786471e..73f3fea 100644 --- a/README.md +++ b/README.md @@ -418,6 +418,11 @@ sections = { -- padding = { left = left_padding, right = right_padding } fmt = nil, -- Format function, formats the component's output. + on_click = nil, -- takes a function that is called when component is clicked with mouse. + -- the function receives several arguments + -- - number of clicks incase of multiple clicks + -- - mouse button used (l(left)/r(right)/m(middle)/...) + -- - modifiers pressed (s(shift)/c(ctrl)/a(alt)/m(meta)...) } } } diff --git a/doc/lualine.txt b/doc/lualine.txt index 6194e92..2f5798c 100644 --- a/doc/lualine.txt +++ b/doc/lualine.txt @@ -431,6 +431,11 @@ General component options These are options that control behavior -- padding = { left = left_padding, right = right_padding } fmt = nil, -- Format function, formats the component's output. + on_click = nil, -- takes a function that is called when component is clicked with mouse. + -- the function receives several arguments + -- - number of clicks incase of multiple clicks + -- - mouse button used (l(left)/r(right)/m(middle)/...) + -- - modifiers pressed (s(shift)/c(ctrl)/a(alt)/m(meta)...) } } } diff --git a/lua/lualine/component.lua b/lua/lualine/component.lua index 8b92a4b..1fe8304 100644 --- a/lua/lualine/component.lua +++ b/lua/lualine/component.lua @@ -1,12 +1,17 @@ -- Copyright (c) 2020-2021 shadmansaleh -- MIT license, see LICENSE for more details. -local require = require('lualine_require').require -local highlight = require('lualine.highlight') +local lualine_require = require('lualine_require') +local require = lualine_require.require local M = require('lualine.utils.class'):extend() +local modules = lualine_require.lazy_require { + highlight = 'lualine.highlight', + utils_notices = 'lualine.utils.notices', + fn_store = 'lualine.utils.fn_store', +} -- Used to provide a unique id for each component local component_no = 1 -function M._reset_component_id() +function M._reset_components() component_no = 1 end @@ -34,6 +39,7 @@ function M:init(options) self.component_no = component_no self:set_separator() self:create_option_highlights() + self:set_on_click() end ---sets the default separator for component based on whether the component @@ -62,6 +68,20 @@ function M:create_option_highlights() end end +---Setup on click function so they can be added during drawing. +function M:set_on_click() + if self.options.on_click ~= nil then + if vim.fn.has('nvim-0.8') == 0 then + modules.utils_notices.add_notice( + '### Options.on_click\nSorry `on_click` can only be used in neovim 0.8 or higher.\n' + ) + self.options.on_click = nil + return + end + self.on_click_id = modules.fn_store.register_fn(self.component_no, self.options.on_click) + end +end + ---adds spaces to left and right of a component function M:apply_padding() local padding = self.options.padding @@ -181,6 +201,13 @@ function M:apply_section_separators() end end +---Add on click funtion description to already drawn item +function M:apply_on_click() + if self.on_click_id then + self.status = self:format_fn(self.on_click_id, self.status) + end +end + ---remove separator from tail of this component. ---called by lualine.utils.sections.draw_section to manage unnecessary separators function M:strip_separator() @@ -198,7 +225,7 @@ function M:get_default_hl() elseif self.default_hl then return self.default_hl else - return highlight.format_highlight(self.options.self.section) + return modules.highlight.format_highlight(self.options.self.section) end end @@ -208,14 +235,22 @@ end ---@return table an identifier to later retrieve the hl for application function M:create_hl(color, hint) hint = hint and self.options.component_name .. '_' .. hint or self.options.component_name - return highlight.create_component_highlight_group(color, hint, self.options, false) + return modules.highlight.create_component_highlight_group(color, hint, self.options, false) end ---Get stl formatted hl group for hl_token ---@param hl_token table identifier received from create_hl or create_component_highlight_group ---@return string stl formatted hl group for hl_token function M:format_hl(hl_token) - return highlight.component_format_highlight(hl_token) + return modules.highlight.component_format_highlight(hl_token) +end + +---Wrap str with click format for function of id +---@param id number +---@param str string +---@return string +function M:format_fn(id, str) + return string.format("%%%d@v:lua.require'lualine.utils.fn_store'.call_fn@%s%%T", id, str) end -- luacheck: push no unused args @@ -244,6 +279,7 @@ function M:draw(default_highlight, is_focused) self:apply_icon() self:apply_padding() self:apply_highlights(default_highlight) + self:apply_on_click() self:apply_section_separators() self:apply_separator() end diff --git a/lua/lualine/utils/fn_store.lua b/lua/lualine/utils/fn_store.lua new file mode 100644 index 0000000..fc4079a --- /dev/null +++ b/lua/lualine/utils/fn_store.lua @@ -0,0 +1,38 @@ +local M = {} +local fns = {} + +---Store fn with id in fns so it can be later called +---@param id integer component id (for now we are only doing one fn per component) +---@param fn function the actual function to store. +---@return number same id that was provided. +function M.register_fn(id, fn) + vim.validate({ + id = {id, 'n'}, + fn = {fn, 'f'} + }) + fns[id] = fn + return id +end + +---Get the function with id +---@param id number id of the fn to retrive +---@return function +function M.get_fn(id) + vim.validate({ id = {id, 'n'} }) + return fns[id] or function () end +end + +---Call the function of id with args +---@param id number +---@param ... any +---@return any +function M.call_fn(id, ...) + return M.get_fn(id)(...) +end + +---Clear the fns table +function M.clear_fns() + fns = {} +end + +return M diff --git a/lua/lualine/utils/loader.lua b/lua/lualine/utils/loader.lua index e391559..74f58bc 100644 --- a/lua/lualine/utils/loader.lua +++ b/lua/lualine/utils/loader.lua @@ -6,6 +6,7 @@ local require = lualine_require.require local modules = lualine_require.lazy_require { utils = 'lualine.utils.utils', notice = 'lualine.utils.notices', + fn_store = 'lualine.utils.fn_store', } local is_valid_filename = lualine_require.is_valid_filename local sep = lualine_require.sep @@ -202,7 +203,8 @@ end ---loads sections and extensions or entire user config ---@param config table user config local function load_all(config) - require('lualine.component')._reset_component_id() + require('lualine.component')._reset_components() + modules.fn_store.clear_fns() load_components(config) load_extensions(config) end