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?
This commit is contained in:
mpaulson 2023-11-28 20:34:00 -07:00
parent b22cb4a873
commit 6fdff8bc41
5 changed files with 84 additions and 7 deletions

View File

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

View File

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

View File

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

View File

@ -0,0 +1,57 @@
---@alias HarpoonListener fun(type: string, args: any[] | any | nil): nil
---@class HarpoonListeners
---@field listeners (HarpoonListener)[]
---@field listenersByType (table<string, HarpoonListener>)[]
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",
},
}

View File

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