fix(dir): custom 3P directory-browser #40725

Problem:
Third-party directory browsers do not have a documented way to take over local
directory buffers from nvim.dir.

Solution:
Document deleting the nvim.dir augroup and handling FileType directory as the
after-startup handoff, and avoid installing the built-in buffer-local "-" mapping
when "-" is already mapped.
This commit is contained in:
Barrett Ruth
2026-07-16 13:26:01 -05:00
committed by GitHub
parent c15ac3d64c
commit 9edf57e665
3 changed files with 60 additions and 15 deletions

View File

@@ -53,6 +53,28 @@ To disable the built-in directory browser, set this before startup: >lua
vim.g.loaded_nvim_dir_plugin = 1
<
Replacing the directory browser *dir-replace-browser*
To use another directory browser for the current session, delete the
`nvim.dir` autocommand group on or after |VimEnter| and handle |FileType| "directory":
>lua
vim.api.nvim_del_augroup_by_name('nvim.dir')
vim.api.nvim_create_autocmd('FileType', {
pattern = 'directory',
callback = function(args)
require('my_browser').open(args.buf, vim.api.nvim_buf_get_name(args.buf))
end,
})
<
This stops the built-in directory-opening autocommands. The plugin and its
mappings remain loaded.
Define replacement keymaps explicitly, for example: >lua
vim.keymap.set('n', '-', function()
require('my_browser').open_parent()
end)
<
Mappings: *dir-mappings*
>
- Open the parent directory of the current file or directory.
@@ -66,7 +88,9 @@ Directory buffer mappings: *dir-buffer-mappings*
<
These keys map to <Plug>(nvim-dir-open), <Plug>(nvim-dir-up), and
<Plug>(nvim-dir-reload); map those to use different keys.
<Plug>(nvim-dir-reload); map those to use different keys. Default mappings are
skipped when the target <Plug> mapping is already mapped. The default global and
directory-buffer "-" mappings are also skipped when "-" is already mapped.
The listing is read-only and does not modify the filesystem.

View File

@@ -185,8 +185,15 @@ local function set_maps(buf)
vim.keymap.set('n', lhs, plug, { buffer = buf, silent = true })
end
end
---@param lhs string
---@param plug string
local function default_map(lhs, plug)
if vim.fn.mapcheck(lhs, 'n') == '' and vim.fn.hasmapto(plug, 'n') == 0 then
vim.keymap.set('n', lhs, plug, { buffer = buf, silent = true })
end
end
map('<CR>', '<Plug>(nvim-dir-open)')
map('-', '<Plug>(nvim-dir-up)')
default_map('-', '<Plug>(nvim-dir-up)')
map('R', '<Plug>(nvim-dir-reload)')
end

View File

@@ -56,6 +56,15 @@ local function filesystem_root(path)
return root
end
local function write_config_plugin(path, text)
local plugin_file = vim.fs.joinpath(vim.fn.stdpath('config'), path)
vim.fs.mkdir(vim.fs.dirname(plugin_file), { parents = true })
finally(function()
os.remove(plugin_file)
end)
t.write_file(plugin_file, text)
end
---@param args? string[]
---@return string[]
local function with_buftype_optionset(args)
@@ -194,25 +203,30 @@ describe('nvim.dir', function()
eq('alpha.txt', api.nvim_get_current_line())
end)
it('startup plugins can replace the `-` mapping', function()
local plugin_file = vim.fs.joinpath(vim.fn.stdpath('config'), 'plugin/dirvish.lua')
vim.fs.mkdir(vim.fs.dirname(plugin_file), { parents = true })
finally(function()
os.remove(plugin_file) -- XXX: Remove file only, to avoid n.rmdir() hang on Windows.
end)
vim.fn.writefile(
it('does not shadow startup plugin `-` mappings in directory buffers', function()
make_fixture()
write_config_plugin(
'plugin/dirvish.lua',
[[
if vim.fn.mapcheck('-', 'n') == '' and vim.fn.hasmapto('<Plug>(dirvish_up)', 'n') == 0 then
vim.keymap.set('n', '-', '<Plug>(dirvish_up)')
end
]],
plugin_file
vim.g.dirvish_up = 0
vim.keymap.set('n', '-', function()
vim.g.dirvish_up = vim.g.dirvish_up + 1
end)
]]
)
n.clear({ args_rm = { '-u', '--cmd' } })
eq(1, fn.exists('g:loaded_nvim_dir_plugin')) -- Avoid false negatives.
eq('<Plug>(dirvish_up)', fn.mapcheck('-', 'n'))
edit(root)
assert_directory(root)
eq(0, fn.maparg('-', 'n', false, true).buffer)
feed('-')
poke_eventloop()
eq(1, exec_lua('return vim.g.dirvish_up'))
assert_directory(root)
end)
it('preserves alternate buffer when opening a parent directory', function()