feat: harpoon extensions

This commit is contained in:
mpaulson 2023-12-14 20:09:55 -07:00
parent 8f67088e9d
commit 9e869aae22
5 changed files with 83 additions and 82 deletions

View 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",
},
}

View File

@ -3,13 +3,13 @@ local Ui = require("harpoon.ui")
local Data = require("harpoon.data")
local Config = require("harpoon.config")
local List = require("harpoon.list")
local Listeners = require("harpoon.listeners")
local Extensions = require("harpoon.extensions")
local HarpoonGroup = require("harpoon.autocmd")
---@class Harpoon
---@field config HarpoonConfig
---@field ui HarpoonUI
---@field listeners HarpoonListeners
---@field _extensions HarpoonExtensions
---@field data HarpoonData
---@field logger HarpoonLog
---@field lists {[string]: {[string]: HarpoonList}}
@ -27,7 +27,7 @@ function Harpoon:new()
data = Data.Data:new(),
logger = Log,
ui = Ui:new(config.settings),
listeners = Listeners.listeners,
_extensions = Extensions.extensions,
lists = {},
hooks_setup = false,
}, self)
@ -62,6 +62,7 @@ function Harpoon:list(name)
local list_config = Config.get_config(self.config, name)
local list = List.decode(list_config, name, data)
self._extensions:emit(Extensions.event_names.LIST_CREATED, list)
lists[name] = list
return list
@ -109,6 +110,11 @@ function Harpoon:dump()
return self.data._data
end
---@param extension HarpoonExtension
function Harpoon:extend(extension)
self._extensions:add_listener(extension)
end
function Harpoon:__debug_reset()
require("plenary.reload").reload_module("harpoon")
end
@ -128,6 +134,7 @@ function Harpoon.setup(self, partial_config)
---@diagnostic disable-next-line: param-type-mismatch
self.config = Config.merge_config(partial_config, self.config)
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?

View File

@ -1,5 +1,5 @@
local Logger = require("harpoon.logger")
local Listeners = require("harpoon.listeners")
local Extensions = require("harpoon.extensions")
--- @class HarpoonNavOptions
--- @field ui_nav_wrap? boolean
@ -57,8 +57,8 @@ function HarpoonList:append(item)
local index = index_of(self.items, item, self.config)
Logger:log("HarpoonList:append", { item = item, index = index })
if index == -1 then
Listeners.listeners:emit(
Listeners.event_names.ADD,
Extensions.extensions:emit(
Extensions.event_names.ADD,
{ list = self, item = item, idx = #self.items + 1 }
)
table.insert(self.items, item)
@ -73,8 +73,8 @@ function HarpoonList:prepend(item)
local index = index_of(self.items, item, self.config)
Logger:log("HarpoonList:prepend", { item = item, index = index })
if index == -1 then
Listeners.listeners:emit(
Listeners.event_names.ADD,
Extensions.extensions:emit(
Extensions.event_names.ADD,
{ list = self, item = item, idx = 1 }
)
table.insert(self.items, 1, item)
@ -88,8 +88,8 @@ function HarpoonList:remove(item)
item = item or self.config.create_list_item(self.config)
for i, v in ipairs(self.items) do
if self.config.equals(v, item) then
Listeners.listeners:emit(
Listeners.event_names.REMOVE,
Extensions.extensions:emit(
Extensions.event_names.REMOVE,
{ list = self, item = item, idx = i }
)
Logger:log("HarpoonList:remove", { item = item, index = i })
@ -107,8 +107,8 @@ function HarpoonList:removeAt(index)
"HarpoonList:removeAt",
{ item = self.items[index], index = index }
)
Listeners.listeners:emit(
Listeners.event_names.REMOVE,
Extensions.extensions:emit(
Extensions.event_names.REMOVE,
{ list = self, item = self.items[index], idx = index }
)
table.remove(self.items, index)
@ -139,8 +139,8 @@ function HarpoonList:resolve_displayed(displayed)
for i, v in ipairs(list_displayed) do
local index = index_of(displayed, v)
if index == -1 then
Listeners.listeners:emit(
Listeners.event_names.REMOVE,
Extensions.extensions:emit(
Extensions.event_names.REMOVE,
{ list = self, item = self.items[i], idx = i }
)
end
@ -150,14 +150,14 @@ function HarpoonList:resolve_displayed(displayed)
local index = index_of(list_displayed, v)
if index == -1 then
new_list[i] = self.config.create_list_item(self.config, v)
Listeners.listeners:emit(
Listeners.event_names.ADD,
Extensions.extensions:emit(
Extensions.event_names.ADD,
{ list = self, item = new_list[i], idx = i }
)
else
if index ~= i then
Listeners.listeners:emit(
Listeners.event_names.REORDER,
Extensions.extensions:emit(
Extensions.event_names.REORDER,
{ list = self, item = self.items[index], idx = i }
)
end
@ -175,8 +175,8 @@ end
function HarpoonList:select(index, options)
local item = self.items[index]
if item or self.config.select_with_nil then
Listeners.listeners:emit(
Listeners.event_names.SELECT,
Extensions.extensions:emit(
Extensions.event_names.SELECT,
{ list = self, item = item, idx = index }
)
self.config.select(item, self, options)

View File

@ -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",
},
}

View File

@ -1,6 +1,6 @@
local Buffer = require("harpoon.buffer")
local Logger = require("harpoon.logger")
local Listeners = require("harpoon.listeners")
local Extensions = require("harpoon.extensions")
---@class HarpoonToggleOptions
---@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,
})
Listeners.listeners:emit(Listeners.event_names.UI_CREATE, {
Extensions.extensions:emit(Extensions.event_names.UI_CREATE, {
win_id = win_id,
bufnr = bufnr,
})