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 = {}
|
local M = {}
|
||||||
|
|
||||||
---@alias HarpoonListItem {value: any, context: any}
|
---@alias HarpoonListItem {value: any, context: any}
|
||||||
@ -19,7 +21,6 @@ local M = {}
|
|||||||
---@field width number
|
---@field width number
|
||||||
---@field height number
|
---@field height number
|
||||||
|
|
||||||
|
|
||||||
---notehunthoeunthoeunthoeunthoeunthoeunth
|
---notehunthoeunthoeunthoeunthoeunthoeunth
|
||||||
---@class HarpoonSettings
|
---@class HarpoonSettings
|
||||||
---@field save_on_toggle boolean defaults to true
|
---@field save_on_toggle boolean defaults to true
|
||||||
@ -31,7 +32,6 @@ local M = {}
|
|||||||
---@field jump_to_file_location? boolean
|
---@field jump_to_file_location? boolean
|
||||||
---@field key? (fun(): string)
|
---@field key? (fun(): string)
|
||||||
|
|
||||||
|
|
||||||
---@class HarpoonConfig
|
---@class HarpoonConfig
|
||||||
---@field default HarpoonPartialConfigItem
|
---@field default HarpoonPartialConfigItem
|
||||||
---@field settings HarpoonSettings
|
---@field settings HarpoonSettings
|
||||||
|
@ -2,6 +2,7 @@ local Ui = require("harpoon2.ui")
|
|||||||
local Data = require("harpoon2.data")
|
local Data = require("harpoon2.data")
|
||||||
local Config = require("harpoon2.config")
|
local Config = require("harpoon2.config")
|
||||||
local List = require("harpoon2.list")
|
local List = require("harpoon2.list")
|
||||||
|
local Listeners = require("harpoon2.listeners")
|
||||||
|
|
||||||
-- setup
|
-- setup
|
||||||
-- read from a config file
|
-- read from a config file
|
||||||
@ -14,6 +15,7 @@ local DEFAULT_LIST = "__harpoon_files"
|
|||||||
---@class Harpoon
|
---@class Harpoon
|
||||||
---@field config HarpoonConfig
|
---@field config HarpoonConfig
|
||||||
---@field ui HarpoonUI
|
---@field ui HarpoonUI
|
||||||
|
---@field listeners HarpoonListeners
|
||||||
---@field data HarpoonData
|
---@field data HarpoonData
|
||||||
---@field lists {[string]: {[string]: HarpoonList}}
|
---@field lists {[string]: {[string]: HarpoonList}}
|
||||||
---@field hooks_setup boolean
|
---@field hooks_setup boolean
|
||||||
@ -29,6 +31,7 @@ function Harpoon:new()
|
|||||||
config = config,
|
config = config,
|
||||||
data = Data.Data:new(),
|
data = Data.Data:new(),
|
||||||
ui = Ui:new(config.settings),
|
ui = Ui:new(config.settings),
|
||||||
|
listeners = Listeners.listeners,
|
||||||
lists = {},
|
lists = {},
|
||||||
hooks_setup = false,
|
hooks_setup = false,
|
||||||
}, self)
|
}, self)
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
local Listeners = require("harpoon2.listeners")
|
||||||
|
|
||||||
local function index_of(items, element, config)
|
local function index_of(items, element, config)
|
||||||
local equals = config and config.equals or function(a, b) return a == b end
|
local equals = config and config.equals or function(a, b) return a == b end
|
||||||
local index = -1
|
local index = -1
|
||||||
@ -43,6 +45,7 @@ function HarpoonList:append(item)
|
|||||||
|
|
||||||
local index = index_of(self.items, item, self.config)
|
local index = index_of(self.items, item, self.config)
|
||||||
if index == -1 then
|
if index == -1 then
|
||||||
|
Listeners.listeners:emit(Listeners.event_names.ADD, {list = self, item = item, idx = #self.items + 1})
|
||||||
table.insert(self.items, item)
|
table.insert(self.items, item)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -54,6 +57,7 @@ function HarpoonList:prepend(item)
|
|||||||
item = item or self.config.add()
|
item = item or self.config.add()
|
||||||
local index = index_of(self.items, item, self.config)
|
local index = index_of(self.items, item, self.config)
|
||||||
if index == -1 then
|
if index == -1 then
|
||||||
|
Listeners.listeners:emit(Listeners.event_names.ADD, {list = self, item = item, idx = 1})
|
||||||
table.insert(self.items, 1, item)
|
table.insert(self.items, 1, item)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -64,6 +68,7 @@ end
|
|||||||
function HarpoonList:remove(item)
|
function HarpoonList:remove(item)
|
||||||
for i, v in ipairs(self.items) do
|
for i, v in ipairs(self.items) do
|
||||||
if self.config.equals(v, item) then
|
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)
|
table.remove(self.items, i)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
@ -73,6 +78,7 @@ end
|
|||||||
|
|
||||||
---@return HarpoonList
|
---@return HarpoonList
|
||||||
function HarpoonList:removeAt(index)
|
function HarpoonList:removeAt(index)
|
||||||
|
Listeners.listeners:emit(Listeners.event_names.REMOVE, {list = self, item = self.items[index], idx = index})
|
||||||
table.remove(self.items, index)
|
table.remove(self.items, index)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -97,17 +103,25 @@ function HarpoonList:resolve_displayed(displayed)
|
|||||||
local new_list = {}
|
local new_list = {}
|
||||||
|
|
||||||
local list_displayed = self:display()
|
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)
|
local index = index_of(list_displayed, v)
|
||||||
if index == -1 then
|
if index == -1 then
|
||||||
table.insert(new_list, self.config.add(v))
|
Listeners.listeners:emit(Listeners.event_names.REMOVE, {list = self, item = v, idx = i})
|
||||||
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])
|
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
self.items = new_list
|
self.items = new_list
|
||||||
@ -116,6 +130,7 @@ end
|
|||||||
function HarpoonList:select(index, options)
|
function HarpoonList:select(index, options)
|
||||||
local item = self.items[index]
|
local item = self.items[index]
|
||||||
if item then
|
if item then
|
||||||
|
Listeners.listeners:emit(Listeners.event_names.SELECT, {list = self, item = item, idx = index})
|
||||||
self.config.select(item, options)
|
self.config.select(item, options)
|
||||||
end
|
end
|
||||||
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 bufnr = harpoon.ui.bufnr
|
||||||
local win_id = harpoon.ui.win_id
|
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()
|
harpoon.ui:toggle_quick_menu()
|
||||||
|
|
||||||
eq(vim.api.nvim_buf_is_valid(bufnr), false)
|
eq(vim.api.nvim_buf_is_valid(bufnr), false)
|
||||||
@ -20,7 +23,6 @@ describe("harpoon", function()
|
|||||||
eq(harpoon.ui.bufnr, nil)
|
eq(harpoon.ui.bufnr, nil)
|
||||||
eq(harpoon.ui.win_id, nil)
|
eq(harpoon.ui.win_id, nil)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user