From 6fdff8bc4121ad9261f3ac13609ead3e643b92ec Mon Sep 17 00:00:00 2001 From: mpaulson Date: Tue, 28 Nov 2023 20:34:00 -0700 Subject: [PATCH] feat: listeners for list actions one thing to consider is if we want to add filtering to the listeners by list? or should we move the listeners to the list? --- lua/harpoon2/config.lua | 6 ++-- lua/harpoon2/init.lua | 3 ++ lua/harpoon2/list.lua | 21 +++++++++++-- lua/harpoon2/listeners.lua | 57 +++++++++++++++++++++++++++++++++++ lua/harpoon2/test/ui_spec.lua | 4 ++- 5 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 lua/harpoon2/listeners.lua diff --git a/lua/harpoon2/config.lua b/lua/harpoon2/config.lua index f3ec2da3..d05c98dd 100644 --- a/lua/harpoon2/config.lua +++ b/lua/harpoon2/config.lua @@ -1,4 +1,6 @@ -local utils = require("harpoon2.utils") +local Listeners = require("harpoon2.listeners") +local listeners = Listeners.listeners + local M = {} ---@alias HarpoonListItem {value: any, context: any} @@ -19,7 +21,6 @@ local M = {} ---@field width number ---@field height number - ---notehunthoeunthoeunthoeunthoeunthoeunth ---@class HarpoonSettings ---@field save_on_toggle boolean defaults to true @@ -31,7 +32,6 @@ local M = {} ---@field jump_to_file_location? boolean ---@field key? (fun(): string) - ---@class HarpoonConfig ---@field default HarpoonPartialConfigItem ---@field settings HarpoonSettings diff --git a/lua/harpoon2/init.lua b/lua/harpoon2/init.lua index 25829d9d..60246ed2 100644 --- a/lua/harpoon2/init.lua +++ b/lua/harpoon2/init.lua @@ -2,6 +2,7 @@ local Ui = require("harpoon2.ui") local Data = require("harpoon2.data") local Config = require("harpoon2.config") local List = require("harpoon2.list") +local Listeners = require("harpoon2.listeners") -- setup -- read from a config file @@ -14,6 +15,7 @@ local DEFAULT_LIST = "__harpoon_files" ---@class Harpoon ---@field config HarpoonConfig ---@field ui HarpoonUI +---@field listeners HarpoonListeners ---@field data HarpoonData ---@field lists {[string]: {[string]: HarpoonList}} ---@field hooks_setup boolean @@ -29,6 +31,7 @@ function Harpoon:new() config = config, data = Data.Data:new(), ui = Ui:new(config.settings), + listeners = Listeners.listeners, lists = {}, hooks_setup = false, }, self) diff --git a/lua/harpoon2/list.lua b/lua/harpoon2/list.lua index 21d86810..1e60cc4c 100644 --- a/lua/harpoon2/list.lua +++ b/lua/harpoon2/list.lua @@ -1,3 +1,5 @@ +local Listeners = require("harpoon2.listeners") + local function index_of(items, element, config) local equals = config and config.equals or function(a, b) return a == b end local index = -1 @@ -43,6 +45,7 @@ function HarpoonList:append(item) local index = index_of(self.items, item, self.config) if index == -1 then + Listeners.listeners:emit(Listeners.event_names.ADD, {list = self, item = item, idx = #self.items + 1}) table.insert(self.items, item) end @@ -54,6 +57,7 @@ function HarpoonList:prepend(item) item = item or self.config.add() local index = index_of(self.items, item, self.config) if index == -1 then + Listeners.listeners:emit(Listeners.event_names.ADD, {list = self, item = item, idx = 1}) table.insert(self.items, 1, item) end @@ -64,6 +68,7 @@ end function HarpoonList:remove(item) for i, v in ipairs(self.items) do if self.config.equals(v, item) then + Listeners.listeners:emit(Listeners.event_names.REMOVE, {list = self, item = item, idx = i}) table.remove(self.items, i) break end @@ -73,6 +78,7 @@ end ---@return HarpoonList function HarpoonList:removeAt(index) + Listeners.listeners:emit(Listeners.event_names.REMOVE, {list = self, item = self.items[index], idx = index}) table.remove(self.items, index) return self end @@ -97,17 +103,25 @@ function HarpoonList:resolve_displayed(displayed) local new_list = {} local list_displayed = self:display() + + for i, v in ipairs(list_displayed) do + local index = index_of(list_displayed, v) + if index == -1 then + Listeners.listeners:emit(Listeners.event_names.REMOVE, {list = self, item = v, idx = i}) + end + end + for i, v in ipairs(displayed) do local index = index_of(list_displayed, v) if index == -1 then - table.insert(new_list, self.config.add(v)) + Listeners.listeners:emit(Listeners.event_names.ADD, {list = self, item = v, idx = i}) + new_list[i] = self.config.add(v) else local index_in_new_list = index_of(new_list, self.items[index], self.config) if index_in_new_list == -1 then - table.insert(new_list, self.items[index]) + new_list[i] = self.items[index] end end - end self.items = new_list @@ -116,6 +130,7 @@ end function HarpoonList:select(index, options) local item = self.items[index] if item then + Listeners.listeners:emit(Listeners.event_names.SELECT, {list = self, item = item, idx = index}) self.config.select(item, options) end end diff --git a/lua/harpoon2/listeners.lua b/lua/harpoon2/listeners.lua new file mode 100644 index 00000000..0a0a08f2 --- /dev/null +++ b/lua/harpoon2/listeners.lua @@ -0,0 +1,57 @@ + +---@alias HarpoonListener fun(type: string, args: any[] | any | nil): nil + +---@class HarpoonListeners +---@field listeners (HarpoonListener)[] +---@field listenersByType (table)[] +local HarpoonListeners = {} + +HarpoonListeners.__index = HarpoonListeners + +function HarpoonListeners:new() + return setmetatable({ + listeners = {}, + listenersByType = {} + }, self) +end + +---@param cbOrType HarpoonListener | string +---@param cbOrNil HarpoonListener | string +function HarpoonListeners:add_listener(cbOrType, cbOrNil) + if (type(cbOrType) == "string") then + if not self.listenersByType[cbOrType] then + self.listenersByType[cbOrType] = {} + end + table.insert(self.listenersByType[cbOrType], cbOrNil) + else + table.insert(self.listeners, cbOrType) + end +end + +function HarpoonListeners:clear_listeners() + self.listeners = {} +end + +---@param type string +---@param args any[] | any | nil +function HarpoonListeners:emit(type, args) + for _, cb in ipairs(self.listeners) do + cb(type, args) + end + + local listeners = self.listenersByType[type] + if listeners ~= nil then + for _, cb in ipairs(listeners) do + cb(type, args) + end + end +end + +return { + listeners = HarpoonListeners:new(), + event_names = { + ADD = "ADD", + SELECT = "SELECT", + REMOVE = "REMOVE", + }, +} diff --git a/lua/harpoon2/test/ui_spec.lua b/lua/harpoon2/test/ui_spec.lua index 3c0cb2dd..de21eb86 100644 --- a/lua/harpoon2/test/ui_spec.lua +++ b/lua/harpoon2/test/ui_spec.lua @@ -13,6 +13,9 @@ describe("harpoon", function() local bufnr = harpoon.ui.bufnr local win_id = harpoon.ui.win_id + eq(vim.api.nvim_buf_is_valid(bufnr), true) + eq(vim.api.nvim_win_is_valid(win_id), true) + harpoon.ui:toggle_quick_menu() eq(vim.api.nvim_buf_is_valid(bufnr), false) @@ -20,7 +23,6 @@ describe("harpoon", function() eq(harpoon.ui.bufnr, nil) eq(harpoon.ui.win_id, nil) end) - end)