mirror of
https://github.com/ThePrimeagen/harpoon.git
synced 2025-07-14 10:00:29 +00:00
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:
parent
b22cb4a873
commit
6fdff8bc41
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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(displayed) do
|
||||
|
||||
for i, v in ipairs(list_displayed) do
|
||||
local index = index_of(list_displayed, v)
|
||||
if index == -1 then
|
||||
table.insert(new_list, 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])
|
||||
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
|
||||
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
|
||||
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
|
||||
|
57
lua/harpoon2/listeners.lua
Normal file
57
lua/harpoon2/listeners.lua
Normal 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",
|
||||
},
|
||||
}
|
@ -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)
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user