-
Notifications
You must be signed in to change notification settings - Fork 258
Recipes
Welcome to the neo-tree.nvim wiki!
This is a place to share configuration recipes for functionality that others may want to copy or learn from.
Sometimes you may want to add a filter and leave that way because the filter captures the files you want to work on now. Other times you may just be using the filter as a quick way to find a file you want to open. In the latter case, you may want to clear the search when you open that file. This custom command offers that choice:
require("neo-tree").setup({
popup_border_style = "NC",
filesystem = {
window = {
mappings = {
["o"] = "open_and_clear_filter"
},
},
commands = {
open_and_clear_filter = function (state)
local node = state.tree:get_node()
if node and node.type == "file" then
local file_path = node:get_id()
-- reuse built-in commands to open and clear filter
local cmds = require("neo-tree.sources.filesystem.commands")
cmds.open(state)
cmds.clear_filter(state)
-- reveal the selected file without focusing the tree
require("neo-tree.sources.filesystem").navigate(state.path, file_path)
end
end,
}
}
})
Components are the blocks of text that get rendered for an item in the tree. Built-in components include things like "icon", "name", or "git_status". Adding a custom component involves two steps: defining a function to implement that component, and then using that component in a renderer.
This example adds the index number of a file that has been marked with Harpoon:
require("neo-tree").setup({
filesystem = {
components = {
harpoon_index = function(config, node, state)
local Marked = require("harpoon.mark")
local path = node:get_id()
local succuss, index = pcall(Marked.get_index_of, path)
if succuss and index and index > 0 then
return {
text = string.format(" ⥤ %d", index), -- <-- Add your favorite harpoon like arrow here
highlight = config.highlight or "NeoTreeDirectoryIcon",
}
else
return {}
end
end
},
renderers = {
file = {
{"icon"},
{"name", use_git_status_colors = true},
{"harpoon_index"}, --> This is what actually adds the component in where you want it
{"diagnostics"},
{"git_status", highlight = "NeoTreeDimText"},
}
}
},
})
This example uses the file_open
event to close the Neo-tree window when a file is opened. This applies to all windows and all sources at once.
require("neo-tree").setup({
event_handlers = {
{
event = "file_opened",
handler = function(file_path)
--auto close
require("neo-tree").close_all()
end
},
}
})
If you want to use the search feature as a fuzzy finder rather than a sticky filter, you may want to clear the search as soon as a file is chosen. One way to handle that was shown above with a custom command, but you could also handle that in a more universal way by handling the "file_opened" event:
require("neo-tree").setup({
event_handlers = {
{
event = "file_opened",
handler = function(file_path)
require("neo-tree.sources.filesystem").reset_search()
end
},
}
})
If you want to take some custom action after a file has been renamed, you can handle the "file_renamed"
in your config and add your code to the handler. The most obvious use for this would be to cleanup references to that file within your project.
require("neo-tree").setup({
events = {
{
event = "file_renamed",
handler = function(args)
-- fix references to file
print(args.source, " renamed to ", args.destination)
end
},
{
event = "file_moved",
handler = function(args)
-- fix references to file
print(args.source, " moved to ", args.destination)
end
},
}
})
If you want to change the logic for where to open a file when using the built-in "open"
, "open_split"
, and "open_vsplit"
commands, the way to do that is by handling the "file_open_requested" event. Below is an example which includes the default logic used by Neo-tree.
NOTE: If you do open the file successfully, you must return { handled = true }
to prevent the next handler from opening the file again. If there are situations where you do want to pass it back to the built-in logic to be handled, return { handled = false }
.
"neo-tree").setup({
event_handlers = {
{
event = "file_open_requested",
handler = function(args)
local state = args.state
local path = args.path
local open_cmd = args.open_cmd or "edit"
-- use last window if possible
local suitable_window_found = false
local nt = require("neo-tree")
if nt.config.open_files_in_last_window then
local prior_window = nt.get_prior_window()
if prior_window > 0 then
local success = pcall(vim.api.nvim_set_current_win, prior_window)
if success then
suitable_window_found = true
end
end
end
-- find a suitable window to open the file in
if not suitable_window_found then
if state.window.position == "right" then
vim.cmd("wincmd t")
else
vim.cmd("wincmd w")
end
end
local attempts = 0
while attempts < 4 and vim.bo.filetype == "neo-tree" do
attempts = attempts + 1
vim.cmd("wincmd w")
end
if vim.bo.filetype == "neo-tree" then
-- Neo-tree must be the only window, restore it's status as a sidebar
local winid = vim.api.nvim_get_current_win()
local width = require("neo-tree.utils").get_value(state, "window.width", 40)
vim.cmd("vsplit " .. path)
vim.api.nvim_win_set_width(winid, width)
else
vim.cmd(open_cmd .. " " .. path)
end
-- If you don't return this, it will proceed to open the file using built-in logic.
return { handled = true }
end
},
},
})