mirror of
https://github.com/ThePrimeagen/harpoon.git
synced 2025-08-29 16:40:24 +00:00
feat: harpoon extensions
This commit is contained in:
parent
8f67088e9d
commit
9e869aae22
54
lua/harpoon/extensions.lua
Normal file
54
lua/harpoon/extensions.lua
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
--- TODO: Rename this... its an odd name "listeners"
|
||||||
|
|
||||||
|
---@class HarpoonExtensions
|
||||||
|
---@field listeners HarpoonExtension[]
|
||||||
|
local HarpoonExtensions = {}
|
||||||
|
|
||||||
|
---@class HarpoonExtension
|
||||||
|
---@field ADD? fun(...): nil
|
||||||
|
---@field SELECT? fun(...): nil
|
||||||
|
---@field REMOVE? fun(...): nil
|
||||||
|
---@field REORDER? fun(...): nil
|
||||||
|
---@field UI_CREATE? fun(...): nil
|
||||||
|
---@field SETUP_CALLED? fun(...): nil
|
||||||
|
---@field LIST_CREATED? fun(...): nil
|
||||||
|
|
||||||
|
HarpoonExtensions.__index = HarpoonExtensions
|
||||||
|
|
||||||
|
function HarpoonExtensions:new()
|
||||||
|
return setmetatable({
|
||||||
|
listeners = {},
|
||||||
|
}, self)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param extension HarpoonExtension
|
||||||
|
function HarpoonExtensions:add_listener(extension)
|
||||||
|
table.insert(self.listeners, extension)
|
||||||
|
end
|
||||||
|
|
||||||
|
function HarpoonExtensions:clear_listeners()
|
||||||
|
self.listeners = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param type string
|
||||||
|
---@param ... any
|
||||||
|
function HarpoonExtensions:emit(type, ...)
|
||||||
|
for _, cb in ipairs(self.listeners) do
|
||||||
|
if cb[type] then
|
||||||
|
cb[type](...)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
extensions = HarpoonExtensions:new(),
|
||||||
|
event_names = {
|
||||||
|
ADD = "ADD",
|
||||||
|
SELECT = "SELECT",
|
||||||
|
REMOVE = "REMOVE",
|
||||||
|
REORDER = "REORDER",
|
||||||
|
UI_CREATE = "UI_CREATE",
|
||||||
|
SETUP_CALLED = "SETUP_CALLED",
|
||||||
|
LIST_CREATED = "LIST_CREATED",
|
||||||
|
},
|
||||||
|
}
|
@ -3,13 +3,13 @@ local Ui = require("harpoon.ui")
|
|||||||
local Data = require("harpoon.data")
|
local Data = require("harpoon.data")
|
||||||
local Config = require("harpoon.config")
|
local Config = require("harpoon.config")
|
||||||
local List = require("harpoon.list")
|
local List = require("harpoon.list")
|
||||||
local Listeners = require("harpoon.listeners")
|
local Extensions = require("harpoon.extensions")
|
||||||
local HarpoonGroup = require("harpoon.autocmd")
|
local HarpoonGroup = require("harpoon.autocmd")
|
||||||
|
|
||||||
---@class Harpoon
|
---@class Harpoon
|
||||||
---@field config HarpoonConfig
|
---@field config HarpoonConfig
|
||||||
---@field ui HarpoonUI
|
---@field ui HarpoonUI
|
||||||
---@field listeners HarpoonListeners
|
---@field _extensions HarpoonExtensions
|
||||||
---@field data HarpoonData
|
---@field data HarpoonData
|
||||||
---@field logger HarpoonLog
|
---@field logger HarpoonLog
|
||||||
---@field lists {[string]: {[string]: HarpoonList}}
|
---@field lists {[string]: {[string]: HarpoonList}}
|
||||||
@ -27,7 +27,7 @@ function Harpoon:new()
|
|||||||
data = Data.Data:new(),
|
data = Data.Data:new(),
|
||||||
logger = Log,
|
logger = Log,
|
||||||
ui = Ui:new(config.settings),
|
ui = Ui:new(config.settings),
|
||||||
listeners = Listeners.listeners,
|
_extensions = Extensions.extensions,
|
||||||
lists = {},
|
lists = {},
|
||||||
hooks_setup = false,
|
hooks_setup = false,
|
||||||
}, self)
|
}, self)
|
||||||
@ -62,6 +62,7 @@ function Harpoon:list(name)
|
|||||||
local list_config = Config.get_config(self.config, name)
|
local list_config = Config.get_config(self.config, name)
|
||||||
|
|
||||||
local list = List.decode(list_config, name, data)
|
local list = List.decode(list_config, name, data)
|
||||||
|
self._extensions:emit(Extensions.event_names.LIST_CREATED, list)
|
||||||
lists[name] = list
|
lists[name] = list
|
||||||
|
|
||||||
return list
|
return list
|
||||||
@ -109,6 +110,11 @@ function Harpoon:dump()
|
|||||||
return self.data._data
|
return self.data._data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---@param extension HarpoonExtension
|
||||||
|
function Harpoon:extend(extension)
|
||||||
|
self._extensions:add_listener(extension)
|
||||||
|
end
|
||||||
|
|
||||||
function Harpoon:__debug_reset()
|
function Harpoon:__debug_reset()
|
||||||
require("plenary.reload").reload_module("harpoon")
|
require("plenary.reload").reload_module("harpoon")
|
||||||
end
|
end
|
||||||
@ -128,6 +134,7 @@ function Harpoon.setup(self, partial_config)
|
|||||||
---@diagnostic disable-next-line: param-type-mismatch
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
self.config = Config.merge_config(partial_config, self.config)
|
self.config = Config.merge_config(partial_config, self.config)
|
||||||
self.ui:configure(self.config.settings)
|
self.ui:configure(self.config.settings)
|
||||||
|
self._extensions:emit(Extensions.event_names.SETUP_CALLED, self.config)
|
||||||
|
|
||||||
---TODO: should we go through every seen list and update its config?
|
---TODO: should we go through every seen list and update its config?
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
local Logger = require("harpoon.logger")
|
local Logger = require("harpoon.logger")
|
||||||
local Listeners = require("harpoon.listeners")
|
local Extensions = require("harpoon.extensions")
|
||||||
|
|
||||||
--- @class HarpoonNavOptions
|
--- @class HarpoonNavOptions
|
||||||
--- @field ui_nav_wrap? boolean
|
--- @field ui_nav_wrap? boolean
|
||||||
@ -57,8 +57,8 @@ function HarpoonList:append(item)
|
|||||||
local index = index_of(self.items, item, self.config)
|
local index = index_of(self.items, item, self.config)
|
||||||
Logger:log("HarpoonList:append", { item = item, index = index })
|
Logger:log("HarpoonList:append", { item = item, index = index })
|
||||||
if index == -1 then
|
if index == -1 then
|
||||||
Listeners.listeners:emit(
|
Extensions.extensions:emit(
|
||||||
Listeners.event_names.ADD,
|
Extensions.event_names.ADD,
|
||||||
{ list = self, item = item, idx = #self.items + 1 }
|
{ list = self, item = item, idx = #self.items + 1 }
|
||||||
)
|
)
|
||||||
table.insert(self.items, item)
|
table.insert(self.items, item)
|
||||||
@ -73,8 +73,8 @@ function HarpoonList:prepend(item)
|
|||||||
local index = index_of(self.items, item, self.config)
|
local index = index_of(self.items, item, self.config)
|
||||||
Logger:log("HarpoonList:prepend", { item = item, index = index })
|
Logger:log("HarpoonList:prepend", { item = item, index = index })
|
||||||
if index == -1 then
|
if index == -1 then
|
||||||
Listeners.listeners:emit(
|
Extensions.extensions:emit(
|
||||||
Listeners.event_names.ADD,
|
Extensions.event_names.ADD,
|
||||||
{ list = self, item = item, idx = 1 }
|
{ list = self, item = item, idx = 1 }
|
||||||
)
|
)
|
||||||
table.insert(self.items, 1, item)
|
table.insert(self.items, 1, item)
|
||||||
@ -88,8 +88,8 @@ function HarpoonList:remove(item)
|
|||||||
item = item or self.config.create_list_item(self.config)
|
item = item or self.config.create_list_item(self.config)
|
||||||
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(
|
Extensions.extensions:emit(
|
||||||
Listeners.event_names.REMOVE,
|
Extensions.event_names.REMOVE,
|
||||||
{ list = self, item = item, idx = i }
|
{ list = self, item = item, idx = i }
|
||||||
)
|
)
|
||||||
Logger:log("HarpoonList:remove", { item = item, index = i })
|
Logger:log("HarpoonList:remove", { item = item, index = i })
|
||||||
@ -107,8 +107,8 @@ function HarpoonList:removeAt(index)
|
|||||||
"HarpoonList:removeAt",
|
"HarpoonList:removeAt",
|
||||||
{ item = self.items[index], index = index }
|
{ item = self.items[index], index = index }
|
||||||
)
|
)
|
||||||
Listeners.listeners:emit(
|
Extensions.extensions:emit(
|
||||||
Listeners.event_names.REMOVE,
|
Extensions.event_names.REMOVE,
|
||||||
{ list = self, item = self.items[index], idx = index }
|
{ list = self, item = self.items[index], idx = index }
|
||||||
)
|
)
|
||||||
table.remove(self.items, index)
|
table.remove(self.items, index)
|
||||||
@ -139,8 +139,8 @@ function HarpoonList:resolve_displayed(displayed)
|
|||||||
for i, v in ipairs(list_displayed) do
|
for i, v in ipairs(list_displayed) do
|
||||||
local index = index_of(displayed, v)
|
local index = index_of(displayed, v)
|
||||||
if index == -1 then
|
if index == -1 then
|
||||||
Listeners.listeners:emit(
|
Extensions.extensions:emit(
|
||||||
Listeners.event_names.REMOVE,
|
Extensions.event_names.REMOVE,
|
||||||
{ list = self, item = self.items[i], idx = i }
|
{ list = self, item = self.items[i], idx = i }
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@ -150,14 +150,14 @@ function HarpoonList:resolve_displayed(displayed)
|
|||||||
local index = index_of(list_displayed, v)
|
local index = index_of(list_displayed, v)
|
||||||
if index == -1 then
|
if index == -1 then
|
||||||
new_list[i] = self.config.create_list_item(self.config, v)
|
new_list[i] = self.config.create_list_item(self.config, v)
|
||||||
Listeners.listeners:emit(
|
Extensions.extensions:emit(
|
||||||
Listeners.event_names.ADD,
|
Extensions.event_names.ADD,
|
||||||
{ list = self, item = new_list[i], idx = i }
|
{ list = self, item = new_list[i], idx = i }
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
if index ~= i then
|
if index ~= i then
|
||||||
Listeners.listeners:emit(
|
Extensions.extensions:emit(
|
||||||
Listeners.event_names.REORDER,
|
Extensions.event_names.REORDER,
|
||||||
{ list = self, item = self.items[index], idx = i }
|
{ list = self, item = self.items[index], idx = i }
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@ -175,8 +175,8 @@ end
|
|||||||
function HarpoonList:select(index, options)
|
function HarpoonList:select(index, options)
|
||||||
local item = self.items[index]
|
local item = self.items[index]
|
||||||
if item or self.config.select_with_nil then
|
if item or self.config.select_with_nil then
|
||||||
Listeners.listeners:emit(
|
Extensions.extensions:emit(
|
||||||
Listeners.event_names.SELECT,
|
Extensions.event_names.SELECT,
|
||||||
{ list = self, item = item, idx = index }
|
{ list = self, item = item, idx = index }
|
||||||
)
|
)
|
||||||
self.config.select(item, self, options)
|
self.config.select(item, self, options)
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
---@alias HarpoonListener fun(type: string, args: any[] | any | nil): nil
|
|
||||||
|
|
||||||
--- TODO: Rename this... its an odd name "listeners"
|
|
||||||
|
|
||||||
---@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",
|
|
||||||
REORDER = "REORDER",
|
|
||||||
UI_CREATE = "UI_CREATE",
|
|
||||||
},
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
local Buffer = require("harpoon.buffer")
|
local Buffer = require("harpoon.buffer")
|
||||||
local Logger = require("harpoon.logger")
|
local Logger = require("harpoon.logger")
|
||||||
local Listeners = require("harpoon.listeners")
|
local Extensions = require("harpoon.extensions")
|
||||||
|
|
||||||
---@class HarpoonToggleOptions
|
---@class HarpoonToggleOptions
|
||||||
---@field border? any this value is directly passed to nvim_open_win
|
---@field border? any this value is directly passed to nvim_open_win
|
||||||
@ -116,7 +116,7 @@ function HarpoonUI:_create_window(toggle_opts)
|
|||||||
win = win_id,
|
win = win_id,
|
||||||
})
|
})
|
||||||
|
|
||||||
Listeners.listeners:emit(Listeners.event_names.UI_CREATE, {
|
Extensions.extensions:emit(Extensions.event_names.UI_CREATE, {
|
||||||
win_id = win_id,
|
win_id = win_id,
|
||||||
bufnr = bufnr,
|
bufnr = bufnr,
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user