mirror of
https://github.com/folke/snacks.nvim
synced 2025-08-04 02:38:46 +00:00
feat(explorer): new explorer
module with shortcut to start explorer picker and netrw replacement functionlity
This commit is contained in:
parent
5420a64b66
commit
670c67366f
6 changed files with 104 additions and 9 deletions
78
lua/snacks/explorer.lua
Normal file
78
lua/snacks/explorer.lua
Normal file
|
@ -0,0 +1,78 @@
|
|||
---@class snacks.explorer
|
||||
---@overload fun(opts?: snacks.picker.explorer.Config): snacks.Picker
|
||||
local M = setmetatable({}, {
|
||||
__call = function(M, ...)
|
||||
return M.open(...)
|
||||
end,
|
||||
})
|
||||
|
||||
M.meta = {
|
||||
desc = "A file explorer (picker in disguise)",
|
||||
needs_setup = true,
|
||||
}
|
||||
|
||||
--- These are just the general explorer settings.
|
||||
--- To configure the explorer picker, see `snacks.picker.explorer.Config`
|
||||
---@class snacks.explorer.Config
|
||||
local defaults = {
|
||||
replace_netrw = true, -- Replace netrw with the snacks explorer
|
||||
}
|
||||
|
||||
---@param event? vim.api.keyset.create_autocmd.callback_args
|
||||
function M.setup(event)
|
||||
local opts = Snacks.config.get("explorer", defaults)
|
||||
if opts.replace_netrw then
|
||||
-- Disable netrw
|
||||
vim.g.loaded_netrw = 1
|
||||
vim.g.loaded_netrwPlugin = 1
|
||||
pcall(vim.api.nvim_del_augroup_by_name, "FileExplorer")
|
||||
|
||||
local group = vim.api.nvim_create_augroup("snacks.explorer", { clear = true })
|
||||
|
||||
local function handle(ev)
|
||||
if ev.file ~= "" and vim.fn.isdirectory(ev.file) == 1 then
|
||||
local picker = M.open({ cwd = ev.file })
|
||||
local ref = picker:ref()
|
||||
if vim.v.vim_did_enter == 0 then
|
||||
-- clear bufname so we don't try loading this one again
|
||||
vim.api.nvim_buf_set_name(ev.buf, "")
|
||||
picker:show()
|
||||
-- focus on UIEnter, since focusing before doesn't work
|
||||
vim.api.nvim_create_autocmd("UIEnter", {
|
||||
once = true,
|
||||
group = group,
|
||||
callback = function()
|
||||
local p = ref()
|
||||
if p then
|
||||
p:_focus()
|
||||
end
|
||||
end,
|
||||
})
|
||||
else
|
||||
-- after vim has entered, we also need to delete the directory buffer
|
||||
-- use bufdelete to keep the window layout
|
||||
Snacks.bufdelete.delete(ev.buf)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- event from snacks loader
|
||||
if event then
|
||||
handle(event)
|
||||
end
|
||||
|
||||
-- Open the explorer when opening a directory
|
||||
vim.api.nvim_create_autocmd("BufEnter", {
|
||||
group = group,
|
||||
callback = handle,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
--- Shortcut to open the explorer picker
|
||||
---@param opts? snacks.picker.explorer.Config|{}
|
||||
function M.open(opts)
|
||||
return Snacks.picker.explorer(opts)
|
||||
end
|
||||
|
||||
return M
|
|
@ -131,17 +131,25 @@ function M.setup(opts)
|
|||
local events = {
|
||||
BufReadPre = { "bigfile" },
|
||||
BufReadPost = { "quickfile", "indent" },
|
||||
BufEnter = { "explorer" },
|
||||
LspAttach = { "words" },
|
||||
UIEnter = { "dashboard", "scroll", "input", "scope", "picker" },
|
||||
}
|
||||
|
||||
local function load(event)
|
||||
for _, snack in ipairs(events[event] or {}) do
|
||||
---@param event string
|
||||
---@param ev? vim.api.keyset.create_autocmd.callback_args
|
||||
local function load(event, ev)
|
||||
local todo = events[event] or {}
|
||||
events[event] = nil
|
||||
for _, snack in ipairs(todo) do
|
||||
if M.config[snack] and M.config[snack].enabled then
|
||||
(M[snack].setup or M[snack].enable)()
|
||||
if M[snack].setup then
|
||||
M[snack].setup(ev)
|
||||
elseif M[snack].enable then
|
||||
M[snack].enable()
|
||||
end
|
||||
end
|
||||
end
|
||||
events[event] = nil
|
||||
end
|
||||
|
||||
if vim.v.vim_did_enter == 1 then
|
||||
|
@ -154,7 +162,7 @@ function M.setup(opts)
|
|||
once = true,
|
||||
nested = true,
|
||||
callback = function(ev)
|
||||
load(ev.event)
|
||||
load(ev.event, ev)
|
||||
end,
|
||||
})
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
---@field dashboard snacks.dashboard
|
||||
---@field debug snacks.debug
|
||||
---@field dim snacks.dim
|
||||
---@field explorer snacks.explorer
|
||||
---@field git snacks.git
|
||||
---@field gitbrowse snacks.gitbrowse
|
||||
---@field health snacks.health
|
||||
|
@ -37,6 +38,7 @@
|
|||
---@field bigfile? snacks.bigfile.Config|{}
|
||||
---@field dashboard? snacks.dashboard.Config|{}
|
||||
---@field dim? snacks.dim.Config|{}
|
||||
---@field explorer? snacks.explorer.Config|{}
|
||||
---@field gitbrowse? snacks.gitbrowse.Config|{}
|
||||
---@field indent? snacks.indent.Config|{}
|
||||
---@field input? snacks.input.Config|{}
|
||||
|
|
|
@ -37,7 +37,7 @@ M.buffers = {
|
|||
},
|
||||
}
|
||||
|
||||
---@class snacks.picker.explorer.Config: snacks.picker.files.Config
|
||||
---@class snacks.picker.explorer.Config: snacks.picker.files.Config|{}
|
||||
---@field follow_file? boolean follow the file from the current buffer
|
||||
---@field tree? boolean show the file tree (default: true)
|
||||
M.explorer = {
|
||||
|
|
|
@ -467,14 +467,18 @@ function M:show()
|
|||
if self.preview.main then
|
||||
self.preview.win:show()
|
||||
end
|
||||
self:_focus()
|
||||
if self.opts.on_show then
|
||||
self.opts.on_show(self)
|
||||
end
|
||||
end
|
||||
|
||||
function M:_focus()
|
||||
if self.opts.focus == "input" then
|
||||
self.input.win:focus()
|
||||
elseif self.opts.focus == "list" then
|
||||
self.list.win:focus()
|
||||
end
|
||||
if self.opts.on_show then
|
||||
self.opts.on_show(self)
|
||||
end
|
||||
end
|
||||
|
||||
---@param item snacks.picker.Item?
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
local M = {}
|
||||
|
||||
---@class snacks.picker
|
||||
---@field explorer fun(opts?: snacks.picker.explorer.Config): snacks.Picker
|
||||
|
||||
---@type table<snacks.Picker, snacks.picker.explorer.State>
|
||||
M._state = setmetatable({}, { __mode = "k" })
|
||||
local uv = vim.uv or vim.loop
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue