Meh I'll figure out submodules later

This commit is contained in:
mustard 2025-09-16 01:01:02 +02:00
parent 4ca9d44a90
commit 8cb281f436
352 changed files with 66107 additions and 0 deletions

View file

@ -0,0 +1,110 @@
local q = require("neo-tree.events.queue")
local log = require("neo-tree.log")
local utils = require("neo-tree.utils")
---@class neotree.event.Functions
local M = {
-- Well known event names, you can make up your own
AFTER_RENDER = "after_render",
BEFORE_FILE_ADD = "before_file_add",
BEFORE_FILE_DELETE = "before_file_delete",
BEFORE_FILE_MOVE = "before_file_move",
BEFORE_FILE_RENAME = "before_file_rename",
BEFORE_RENDER = "before_render",
FILE_ADDED = "file_added",
FILE_DELETED = "file_deleted",
FILE_MOVED = "file_moved",
FILE_OPENED = "file_opened",
FILE_OPEN_REQUESTED = "file_open_requested",
FILE_RENAMED = "file_renamed",
FS_EVENT = "fs_event",
GIT_EVENT = "git_event",
GIT_STATUS_CHANGED = "git_status_changed",
STATE_CREATED = "state_created",
NEO_TREE_BUFFER_ENTER = "neo_tree_buffer_enter",
NEO_TREE_BUFFER_LEAVE = "neo_tree_buffer_leave",
NEO_TREE_LSP_UPDATE = "neo_tree_lsp_update",
NEO_TREE_POPUP_BUFFER_ENTER = "neo_tree_popup_buffer_enter",
NEO_TREE_POPUP_BUFFER_LEAVE = "neo_tree_popup_buffer_leave",
NEO_TREE_POPUP_INPUT_READY = "neo_tree_popup_input_ready",
NEO_TREE_WINDOW_AFTER_CLOSE = "neo_tree_window_after_close",
NEO_TREE_WINDOW_AFTER_OPEN = "neo_tree_window_after_open",
NEO_TREE_WINDOW_BEFORE_CLOSE = "neo_tree_window_before_close",
NEO_TREE_WINDOW_BEFORE_OPEN = "neo_tree_window_before_open",
NEO_TREE_PREVIEW_BEFORE_RENDER = "neo_tree_preview_before_render",
VIM_AFTER_SESSION_LOAD = "vim_after_session_load",
VIM_BUFFER_ADDED = "vim_buffer_added",
VIM_BUFFER_CHANGED = "vim_buffer_changed",
VIM_BUFFER_DELETED = "vim_buffer_deleted",
VIM_BUFFER_ENTER = "vim_buffer_enter",
VIM_BUFFER_MODIFIED_SET = "vim_buffer_modified_set",
VIM_COLORSCHEME = "vim_colorscheme",
VIM_CURSOR_MOVED = "vim_cursor_moved",
VIM_DIAGNOSTIC_CHANGED = "vim_diagnostic_changed",
VIM_DIR_CHANGED = "vim_dir_changed",
VIM_INSERT_LEAVE = "vim_insert_leave",
VIM_LEAVE = "vim_leave",
VIM_LSP_REQUEST = "vim_lsp_request",
VIM_RESIZED = "vim_resized",
VIM_TAB_CLOSED = "vim_tab_closed",
VIM_TERMINAL_ENTER = "vim_terminal_enter",
VIM_TEXT_CHANGED_NORMAL = "vim_text_changed_normal",
VIM_WIN_CLOSED = "vim_win_closed",
VIM_WIN_ENTER = "vim_win_enter",
}
---@param autocmds string
---@return string event
---@return string? pattern
local parse_autocmd_string = function(autocmds)
local parsed = vim.split(autocmds, " ")
return parsed[1], parsed[2]
end
---@param event_name neotree.EventName|string
---@param autocmds string[]
---@param debounce_frequency integer?
---@param seed_fn function?
---@param nested boolean?
M.define_autocmd_event = function(event_name, autocmds, debounce_frequency, seed_fn, nested)
log.debug("Defining autocmd event: %s", event_name)
local augroup_name = "NeoTreeEvent_" .. event_name
q.define_event(event_name, {
setup = function()
local augroup = vim.api.nvim_create_augroup(augroup_name, { clear = false })
for _, autocmd in ipairs(autocmds) do
local event, pattern = parse_autocmd_string(autocmd)
log.trace("Registering autocmds on %s %s", event, pattern or "")
vim.api.nvim_create_autocmd({ event }, {
pattern = pattern or "*",
group = augroup,
nested = nested,
callback = function(args)
---@class neotree.event.Autocmd.CallbackArgs : neotree._vim.api.keyset.create_autocmd.callback_args
---@field afile string
local event_args = args --[[@as neotree._vim.api.keyset.create_autocmd.callback_args]]
event_args.afile = args.file or ""
M.fire_event(event_name, event_args)
end,
})
end
end,
seed = seed_fn,
teardown = function()
log.trace("Teardown autocmds for ", event_name)
vim.api.nvim_create_augroup(augroup_name, { clear = true })
end,
debounce_frequency = debounce_frequency,
debounce_strategy = utils.debounce_strategy.CALL_LAST_ONLY,
})
end
M.clear_all_events = q.clear_all_events
M.define_event = q.define_event
M.destroy_event = q.destroy_event
M.fire_event = q.fire_event
M.subscribe = q.subscribe
M.unsubscribe = q.unsubscribe
return M

View file

@ -0,0 +1,167 @@
local utils = require("neo-tree.utils")
local log = require("neo-tree.log")
local Queue = require("neo-tree.collections").Queue
---@type table<string, neotree.collections.Queue?>
local event_queues = {}
---@type table <string, neotree.event.Definition?>
local event_definitions = {}
local M = {}
---@class neotree.event.Handler.Result
---@field handled boolean?
---@class neotree.event.Handler
---@field event neotree.EventName|string
---@field handler fun(table?):(neotree.event.Handler.Result?)
---@field id string?
local typecheck = require("neo-tree.health.typecheck")
local validate = typecheck.validate
---@param event_handler neotree.event.Handler
local validate_event_handler = function(event_handler)
return validate("event_handler", event_handler, function(eh)
validate("event", eh.event, "string")
validate("handler", eh.handler, "function")
end)
end
M.clear_all_events = function()
for event_name, queue in pairs(event_queues) do
M.destroy_event(event_name)
end
event_queues = {}
end
---@class neotree.event.Definition
---@field teardown function?
---@field setup function?
---@field setup_was_run boolean?
---@param event_name neotree.EventName|string
---@param opts neotree.event.Definition
M.define_event = function(event_name, opts)
local existing = event_definitions[event_name]
if existing ~= nil then
error("Event already defined: " .. event_name)
end
event_definitions[event_name] = opts
end
---@param event_name neotree.EventName|string
---@return boolean existed_and_destroyed
M.destroy_event = function(event_name)
local existing = event_definitions[event_name]
if existing == nil then
return false
end
if existing.setup_was_run and type(existing.teardown) == "function" then
local success, result = pcall(existing.teardown)
if not success then
error("Error in teardown for " .. event_name .. ": " .. result)
end
existing.setup_was_run = false
end
event_queues[event_name] = nil
return true
end
---@param event neotree.EventName|string
---@param args table
local fire_event_internal = function(event, args)
local queue = event_queues[event]
if queue == nil then
return nil
end
--log.trace("Firing event: ", event, " with args: ", args)
if queue:is_empty() then
--log.trace("Event queue is empty")
return nil
end
local seed = utils.get_value(event_definitions, event .. ".seed")
if seed ~= nil then
local success, result = pcall(seed, args)
if success and result then
log.trace("Seed for " .. event .. " returned: " .. tostring(result))
elseif success then
log.trace("Seed for " .. event .. " returned falsy, cancelling event")
else
log.error("Error in seed function for " .. event .. ": " .. result)
end
end
return queue:for_each(function(event_handler)
local remove_node = event_handler == nil or event_handler.cancelled
if not remove_node then
local success, result = pcall(event_handler.handler, args)
local id = event_handler.id or event_handler
if success then
log.trace("Handler ", id, " for " .. event .. " called successfully.")
else
log.error(string.format("Error in event handler for event %s[%s]: %s", event, id, result))
end
if event_handler.once then
event_handler.cancelled = true
return true
end
return result
end
end)
end
---@param event neotree.EventName|string
---@param args any?
M.fire_event = function(event, args)
local freq = utils.get_value(event_definitions, event .. ".debounce_frequency", 0, true)
local strategy = utils.get_value(event_definitions, event .. ".debounce_strategy", 0, true)
log.trace("Firing event: ", event, " with args: ", args)
if freq > 0 then
utils.debounce("EVENT_FIRED: " .. event, function()
fire_event_internal(event, args or {})
end, freq, strategy)
else
return fire_event_internal(event, args or {})
end
end
---@param event_handler neotree.event.Handler
M.subscribe = function(event_handler)
validate_event_handler(event_handler)
local queue = event_queues[event_handler.event]
if queue == nil then
log.debug("Creating queue for event: " .. event_handler.event)
queue = Queue:new()
local def = event_definitions[event_handler.event]
if def and type(def.setup) == "function" then
local success, result = pcall(def.setup)
if success then
def.setup_was_run = true
log.debug("Setup for event " .. event_handler.event .. " was run")
else
log.error("Error in setup for " .. event_handler.event .. ": " .. result)
end
end
event_queues[event_handler.event] = queue
end
log.debug("Adding event handler [", event_handler.id, "] for event: ", event_handler.event)
queue:add(event_handler)
end
---@param event_handler neotree.event.Handler
M.unsubscribe = function(event_handler)
local queue = event_queues[event_handler.event]
if queue == nil then
return nil
end
queue:remove_by_id(event_handler.id or event_handler)
if queue:is_empty() then
M.destroy_event(event_handler.event)
event_queues[event_handler.event] = nil
else
event_queues[event_handler.event] = queue
end
end
return M