diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index da7ae82e1b1..e16c20402a2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -139,7 +139,7 @@ This will: 2. Regenerate from `*nvim-tree-config*` to the end of the file, see `gen_vimdoc.sh` 3. Update default mappings in `*nvim-tree-mappings-default*` and `*nvim-tree-quickstart-help*` -Commit your changes then run: +Commit or stage your changes then run: ```sh make help-check ``` diff --git a/Makefile b/Makefile index d04e92e94d1..4ec53e0bb4a 100644 --- a/Makefile +++ b/Makefile @@ -12,10 +12,8 @@ check: luals # # subtasks # -# TODO #3241 ensure that decorator is checked - all meta should be valid luacheck: - luacheck --codes --quiet lua --exclude-files "**/_meta/api_decorator.lua" - luacheck --codes --quiet scripts + luacheck --codes --quiet lua --exclude-files "**/_meta/**" style-check: scripts/luals-check.sh codestyle-check diff --git a/README.md b/README.md index 057ebf9db96..5bcb3d58fa3 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ local function my_on_attach(bufnr) end -- default mappings - api.config.mappings.default_on_attach(bufnr) + api.map.on_attach.default(bufnr) -- custom mappings vim.keymap.set('n', '', api.tree.change_root_to_parent, opts('Up')) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 0904c5c5106..1fedbd33e12 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -67,7 +67,7 @@ Quickstart: Setup *nvim-tree-quickstart-setup* Setup the plugin in your `init.lua`. -See |nvim-tree-setup| and |nvim-tree-default-config >lua +See |nvim-tree-setup| and |nvim-tree-config-default| >lua -- disable netrw at the very start of your init.lua vim.g.loaded_netrw = 1 @@ -105,65 +105,65 @@ Open the tree: `:NvimTreeOpen` Show the mappings: `g?` -`` CD |nvim-tree-api.tree.change_root_to_node()| -`` Open: In Place |nvim-tree-api.node.open.replace_tree_buffer()| -`` Info |nvim-tree-api.node.show_info_popup()| -`` Rename: Omit Filename |nvim-tree-api.fs.rename_sub()| -`` Open: New Tab |nvim-tree-api.node.open.tab()| -`` Open: Vertical Split |nvim-tree-api.node.open.vertical()| -`` Open: Horizontal Split |nvim-tree-api.node.open.horizontal()| -`` Close Directory |nvim-tree-api.node.navigate.parent_close()| -`` Open |nvim-tree-api.node.open.edit()| -`` Delete |nvim-tree-api.fs.remove()| -`` Open Preview |nvim-tree-api.node.open.preview()| -`>` Next Sibling |nvim-tree-api.node.navigate.sibling.next()| -`<` Previous Sibling |nvim-tree-api.node.navigate.sibling.prev()| -`.` Run Command |nvim-tree-api.node.run.cmd()| -`-` Up |nvim-tree-api.tree.change_root_to_parent()| -`a` Create File Or Directory |nvim-tree-api.fs.create()| -`bd` Delete Bookmarked |nvim-tree-api.marks.bulk.delete()| -`bt` Trash Bookmarked |nvim-tree-api.marks.bulk.trash()| -`bmv` Move Bookmarked |nvim-tree-api.marks.bulk.move()| -`B` Toggle Filter: No Buffer |nvim-tree-api.tree.toggle_no_buffer_filter()| -`c` Copy |nvim-tree-api.fs.copy.node()| -`C` Toggle Filter: Git Clean |nvim-tree-api.tree.toggle_git_clean_filter()| -`[c` Prev Git |nvim-tree-api.node.navigate.git.prev()| -`]c` Next Git |nvim-tree-api.node.navigate.git.next()| -`d` Delete |nvim-tree-api.fs.remove()| -`D` Trash |nvim-tree-api.fs.trash()| -`E` Expand All |nvim-tree-api.tree.expand_all()| -`e` Rename: Basename |nvim-tree-api.fs.rename_basename()| -`]e` Next Diagnostic |nvim-tree-api.node.navigate.diagnostics.next()| -`[e` Prev Diagnostic |nvim-tree-api.node.navigate.diagnostics.prev()| -`F` Live Filter: Clear |nvim-tree-api.live_filter.clear()| -`f` Live Filter: Start |nvim-tree-api.live_filter.start()| -`g?` Help |nvim-tree-api.tree.toggle_help()| -`gy` Copy Absolute Path |nvim-tree-api.fs.copy.absolute_path()| -`ge` Copy Basename |nvim-tree-api.fs.copy.basename()| -`H` Toggle Filter: Dotfiles |nvim-tree-api.tree.toggle_hidden_filter()| -`I` Toggle Filter: Git Ignore |nvim-tree-api.tree.toggle_gitignore_filter()| -`J` Last Sibling |nvim-tree-api.node.navigate.sibling.last()| -`K` First Sibling |nvim-tree-api.node.navigate.sibling.first()| -`L` Toggle Group Empty |nvim-tree-api.node.open.toggle_group_empty()| -`M` Toggle Filter: No Bookmark |nvim-tree-api.tree.toggle_no_bookmark_filter()| -`m` Toggle Bookmark |nvim-tree-api.marks.toggle()| -`o` Open |nvim-tree-api.node.open.edit()| -`O` Open: No Window Picker |nvim-tree-api.node.open.no_window_picker()| -`p` Paste |nvim-tree-api.fs.paste()| -`P` Parent Directory |nvim-tree-api.node.navigate.parent()| -`q` Close |nvim-tree-api.tree.close()| -`r` Rename |nvim-tree-api.fs.rename()| -`R` Refresh |nvim-tree-api.tree.reload()| -`s` Run System |nvim-tree-api.node.run.system()| -`S` Search |nvim-tree-api.tree.search_node()| -`u` Rename: Full Path |nvim-tree-api.fs.rename_full()| -`U` Toggle Filter: Hidden |nvim-tree-api.tree.toggle_custom_filter()| -`W` Collapse All |nvim-tree-api.tree.collapse_all()| -`x` Cut |nvim-tree-api.fs.cut()| -`y` Copy Name |nvim-tree-api.fs.copy.filename()| -`Y` Copy Relative Path |nvim-tree-api.fs.copy.relative_path()| -`<2-LeftMouse>` Open |nvim-tree-api.node.open.edit()| -`<2-RightMouse>` CD |nvim-tree-api.tree.change_root_to_node()| +`` CD |nvim_tree.api.tree.change_root_to_node()| +`` Open: In Place |nvim_tree.api.node.open.replace_tree_buffer()| +`` Info |nvim_tree.api.node.show_info_popup()| +`` Rename: Omit Filename |nvim_tree.api.fs.rename_sub()| +`` Open: New Tab |nvim_tree.api.node.open.tab()| +`` Open: Vertical Split |nvim_tree.api.node.open.vertical()| +`` Open: Horizontal Split |nvim_tree.api.node.open.horizontal()| +`` Close Directory |nvim_tree.api.node.navigate.parent_close()| +`` Open |nvim_tree.api.node.open.edit()| +`` Delete |nvim_tree.api.fs.remove()| +`` Open Preview |nvim_tree.api.node.open.preview()| +`>` Next Sibling |nvim_tree.api.node.navigate.sibling.next()| +`<` Previous Sibling |nvim_tree.api.node.navigate.sibling.prev()| +`.` Run Command |nvim_tree.api.node.run.cmd()| +`-` Up |nvim_tree.api.tree.change_root_to_parent()| +`a` Create File Or Directory |nvim_tree.api.fs.create()| +`bd` Delete Bookmarked |nvim_tree.api.marks.bulk.delete()| +`bt` Trash Bookmarked |nvim_tree.api.marks.bulk.trash()| +`bmv` Move Bookmarked |nvim_tree.api.marks.bulk.move()| +`B` Toggle Filter: No Buffer |nvim_tree.api.filter.no_buffer.toggle()| +`c` Copy |nvim_tree.api.fs.copy.node()| +`C` Toggle Filter: Git Clean |nvim_tree.api.filter.git.clean.toggle()| +`[c` Prev Git |nvim_tree.api.node.navigate.git.prev()| +`]c` Next Git |nvim_tree.api.node.navigate.git.next()| +`d` Delete |nvim_tree.api.fs.remove()| +`D` Trash |nvim_tree.api.fs.trash()| +`E` Expand All |nvim_tree.api.tree.expand_all()| +`e` Rename: Basename |nvim_tree.api.fs.rename_basename()| +`]e` Next Diagnostic |nvim_tree.api.node.navigate.diagnostics.next()| +`[e` Prev Diagnostic |nvim_tree.api.node.navigate.diagnostics.prev()| +`F` Live Filter: Clear |nvim_tree.api.filter.live.clear()| +`f` Live Filter: Start |nvim_tree.api.filter.live.start()| +`g?` Help |nvim_tree.api.tree.toggle_help()| +`gy` Copy Absolute Path |nvim_tree.api.fs.copy.absolute_path()| +`ge` Copy Basename |nvim_tree.api.fs.copy.basename()| +`H` Toggle Filter: Dotfiles |nvim_tree.api.filter.dotfiles.toggle()| +`I` Toggle Filter: Git Ignored |nvim_tree.api.filter.git.ignored.toggle()| +`J` Last Sibling |nvim_tree.api.node.navigate.sibling.last()| +`K` First Sibling |nvim_tree.api.node.navigate.sibling.first()| +`L` Toggle Group Empty |nvim_tree.api.node.open.toggle_group_empty()| +`M` Toggle Filter: No Bookmark |nvim_tree.api.filter.no_bookmark.toggle()| +`m` Toggle Bookmark |nvim_tree.api.marks.toggle()| +`o` Open |nvim_tree.api.node.open.edit()| +`O` Open: No Window Picker |nvim_tree.api.node.open.no_window_picker()| +`p` Paste |nvim_tree.api.fs.paste()| +`P` Parent Directory |nvim_tree.api.node.navigate.parent()| +`q` Close |nvim_tree.api.tree.close()| +`r` Rename |nvim_tree.api.fs.rename()| +`R` Refresh |nvim_tree.api.tree.reload()| +`s` Run System |nvim_tree.api.node.run.system()| +`S` Search |nvim_tree.api.tree.search_node()| +`u` Rename: Full Path |nvim_tree.api.fs.rename_full()| +`U` Toggle Filter: Custom |nvim_tree.api.filter.custom.toggle()| +`W` Collapse All |nvim_tree.api.tree.collapse_all()| +`x` Cut |nvim_tree.api.fs.cut()| +`y` Copy Name |nvim_tree.api.fs.copy.filename()| +`Y` Copy Relative Path |nvim_tree.api.fs.copy.relative_path()| +`<2-LeftMouse>` Open |nvim_tree.api.node.open.edit()| +`<2-RightMouse>` CD |nvim_tree.api.tree.change_root_to_node()| ============================================================================== Quickstart: Custom Mappings *nvim-tree-quickstart-custom-mappings* @@ -179,7 +179,7 @@ via |nvim_tree.config| {on_attach} e.g. >lua end -- default mappings - api.config.mappings.default_on_attach(bufnr) + api.map.on_attach.default(bufnr) -- custom mappings vim.keymap.set("n", "", api.tree.change_root_to_parent, opts("Up")) @@ -213,104 +213,83 @@ See |nvim-tree-highlight-groups| for details. ============================================================================== Commands *nvim-tree-commands* -*:NvimTreeOpen* +Commands may be executed with a `` (`!`) or take a `path` string argument. - Opens the tree. See |nvim-tree-api.tree.open()| +All commands execute public API. - Calls: `api.tree.open({ path = "" })` +*:NvimTreeOpen* |nvim_tree.api.tree.open()| >lua -*:NvimTreeClose* - - Closes the tree. See |nvim-tree-api.tree.close()| - - Calls: `api.tree.close()` - -*:NvimTreeToggle* - - Open or close the tree. See |nvim-tree-api.tree.toggle()| - - Calls: `api.tree.toggle({ path = "", find_file = false, update_root = false, focus = true, })` - -*:NvimTreeFocus* - - Open the tree if it is closed, and then focus on the tree. - - See |nvim-tree-api.tree.open()| - - Calls: `api.tree.open()` - -*:NvimTreeRefresh* - - Refresh the tree. See |nvim-tree-api.tree.reload()| - - Calls: `api.tree.reload()` - -*:NvimTreeFindFile* - - The command will change the cursor in the tree for the current bufname. - - It will also open the leafs of the tree leading to the file in the buffer - (if you opened a file with something else than the NvimTree, like `fzf` or - `:split`) - - Invoke with a bang `:NvimTreeFindFile!` to update the root. - - See |nvim-tree-api.tree.find_file()| - - Calls: `api.tree.find_file({ update_root = , open = true, focus = true, })` - -*:NvimTreeFindFileToggle* - - close the tree or change the cursor in the tree for the current bufname, - similar to combination of |:NvimTreeToggle| and |:NvimTreeFindFile|. Takes an - optional path argument. - - Invoke with a bang `:NvimTreeFindFileToggle!` to update the root. - - See |nvim-tree-api.tree.toggle()| - - Calls: `api.tree.toggle({ path = "", update_root = , find_file = true, focus = true, })` - -*:NvimTreeClipboard* - - Print clipboard content for both cut and copy - - See |nvim-tree-api.fs.print_clipboard()| - - Calls: `api.fs.print_clipboard()` - -*:NvimTreeResize* - - Resize the NvimTree window to the given size. Example: `:NvimTreeResize 50` - resizes the window to the width of 50. If the size starts with "+" or "-" it - adds or removes the given value to the current window width. - Example `:NvimTreeResize -20` removes the value 20 from the current width. And - `:NvimTreeResize +20` adds the value 20 to the current width. - -*:NvimTreeCollapse* + require("nvim-tree.api").tree.open({ + path = "" + }) +< +*:NvimTreeClose* |nvim_tree.api.tree.close()| >lua - Collapses the nvim-tree recursively. + require("nvim-tree.api").tree.close() +< +*:NvimTreeToggle* |nvim_tree.api.tree.toggle()| >lua - See |nvim-tree-api.tree.collapse_all()| + require("nvim-tree.api").tree.toggle({ + path = "", + find_file = false, + update_root = false, + focus = true, + }) +< +*:NvimTreeFocus* |nvim_tree.api.tree.open()| >lua - Calls: `api.tree.collapse_all({ keep_buffers = false })` + require("nvim-tree.api").tree.open() +< +*:NvimTreeRefresh* |nvim_tree.api.tree.reload()| >lua -*:NvimTreeCollapseKeepBuffers* + require("nvim-tree.api").tree.reload() +< +*:NvimTreeFindFile* |nvim_tree.api.tree.find_file()| >lua - Collapses the nvim-tree recursively, but keep the directories open, which are - used in an open buffer. + require("nvim-tree.api").tree.find_file({ + open = true, + update_root = "", + focus = true, + }) +< +*:NvimTreeFindFileToggle* |nvim_tree.api.tree.toggle()| >lua - See |nvim-tree-api.tree.collapse_all()| + require("nvim-tree.api").tree.toggle({ + path = "", + find_file = true, + update_root = "", + focus = true, + }) +< +*:NvimTreeClipboard* |nvim_tree.api.fs.print_clipboard()| >lua - Calls: `api.tree.collapse_all({ keep_buffers = true })` + require("nvim-tree.api").fs.print_clipboard() +< +*:NvimTreeCollapse* |nvim_tree.api.tree.collapse_all()| >lua -*:NvimTreeHiTest* + require("nvim-tree.api").tree.collapse_all({ + keep_buffers = false + }) +< +*:NvimTreeCollapseKeepBuffers* |nvim_tree.api.tree.collapse_all()| >lua - Show nvim-tree highlight groups similar to `:so $VIMRUNTIME/syntax/hitest.vim` + require("nvim-tree.api").tree.collapse_all({ + keep_buffers = true + }) +< +*:NvimTreeHiTest* |nvim_tree.api.health.hi_test()| >lua - See |nvim-tree-api.diagnostics.hi_test()| + require("nvim-tree.api").health.hi_test() +< +*:NvimTreeResize* |nvim_tree.api.tree.resize()| >lua - Calls: `api.diagnostics.hi_test()` + local sign = c.args:sub(1, 1) + if sign == "+" or sign == "-" then + require("nvim-tree.api").tree.resize({ relative = tonumber(c.args) }) + else + require("nvim-tree.api").tree.resize({ absolute = tonumber(c.args) }) + end +< ============================================================================== Setup *nvim-tree-setup* @@ -320,7 +299,7 @@ called again to apply a change in configuration without restarting Nvim. The `setup()` function takes one optional argument: |nvim_tree.config|. If omitted nvim-tree will be initialised with default configuration: -|nvim-tree-default-config|. +|nvim-tree-config-default|. Config can be validated with |lsp| when passed directly e.g. >lua @@ -342,2470 +321,1765 @@ the configuration. Nothing happens until the tree is first opened. Subsequent `setup()` calls are expensive as they tear down the world before applying configuration. - ============================================================================== -API *nvim-tree-api* - -Nvim-tree's public API can be used to access features. e.g. >lua - local api = require("nvim-tree.api") - api.tree.toggle() -< -This module exposes stable functionalities, it is advised to use this in order -to avoid breaking configurations due to internal breaking changes. - -The api is separated in multiple modules, which can be accessed with -`api..` +Mappings *nvim-tree-mappings* -Functions accepting {node} as their first argument will use the node under the -cursor when that argument is not present or nil. +Mappings are set via the |nvim_tree.config| {on_attach} function, which is run upon +creating the nvim-tree buffer. Mappings are usually |nvim-tree-api| functions +however may be your own. -============================================================================== -API: Tree *nvim-tree-api.tree* +When {on_attach} is not a function, |nvim-tree-mappings-default| will be used. -tree.open({opts}) *nvim-tree-api.tree.open()* - Open the tree, focusing it if already open. +Active mappings may be viewed via HELP, default `g?`. The mapping's description +is used when displaying HELP. - Parameters: ~ - • {opts} (table) optional parameters +The `on_attach` function is passed the `bufnr` of nvim-tree. Use +|vim.keymap.set()| or |nvim_set_keymap()| to define mappings as usual. e.g. >lua - Options: ~ - • {path} (string) root directory for the tree - • {current_window} (boolean) open the tree in the current window - • {winid} (number) open the tree in the specified |winid|, - overrides {current_window} - • {find_file} (boolean) find the current buffer - • {update_root} (boolean) requires {find_file}, see - |nvim_tree.config.update_focused_file| {update_root} + local function my_on_attach(bufnr) + local api = require("nvim-tree.api") -tree.toggle({opts}) *nvim-tree-api.tree.toggle()* - Open or close the tree. + local function opts(desc) + return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true } + end - Parameters: ~ - • {opts} (table) optional parameters + -- copy default mappings here from defaults in next section + vim.keymap.set("n", "", api.tree.change_root_to_node, opts("CD")) + vim.keymap.set("n", "", api.node.open.replace_tree_buffer, opts("Open: In Place")) + --- + -- OR use all default mappings + api.map.on_attach.default.on_attach_default(bufnr) - Options: ~ - • {path} (string) root directory for the tree - • {current_window} (boolean) open the tree in the current window - • {winid} (number) open the tree in the specified |winid|, - overrides {current_window} - • {find_file} (boolean) find the current buffer - • {update_root} (boolean) requires {find_file}, see - |nvim_tree.config.update_focused_file| {update_root} - • {focus} (boolean) focus the tree when opening, default true + -- remove a default + vim.keymap.del("n", "", { buffer = bufnr }) -tree.close() *nvim-tree-api.tree.close()* - Close the tree, affecting all tabs as per |nvim_tree.config.tab.sync| {close} + -- override a default + vim.keymap.set("n", "", api.tree.reload, opts("Refresh")) -tree.close_in_this_tab() *nvim-tree-api.tree.close_in_this_tab()* - Close the tree in this tab only. + -- add your mappings + vim.keymap.set("n", "?", api.tree.toggle_help, opts("Help")) + --- + end -tree.close_in_all_tabs() *nvim-tree-api.tree.close_in_all_tabs()* - Close the tree in all tabs. + require("nvim-tree").setup({ + --- + on_attach = my_on_attach, + --- + }) +< +Single left mouse mappings can be achieved via ``. -tree.focus() *nvim-tree-api.tree.focus()* - Focus the tree, opening it if necessary. - Retained for compatibility, use |nvim-tree-api.tree.open()| with no arguments instead. +Single right / middle mouse mappings will require changes to |'mousemodel'| or |'mouse'|. -tree.reload() *nvim-tree-api.tree.reload()* - Refresh the tree. Does nothing if closed. +|vim.keymap.set()| {rhs} is a `(function|string)` thus it may be necessary to +define your own function to map complex functionality e.g. >lua -tree.resize({opts}) *nvim-tree-api.tree.resize()* - Resize the tree, persisting the new size. - Resets to |nvim_tree.config.view| {width} when no {opts} provided. - See |:NvimTreeResize| + local function print_node_path() + local api = require("nvim-tree.api") + local node = api.tree.get_node_under_cursor() + print(node.absolute_path) + end - Parameters: ~ - • {opts} (table) optional parameters + -- on_attach + vim.keymap.set("n", "", print_node_path, opts("Print Path")) +< +============================================================================== +Mappings: Default *nvim-tree-mappings-default* - Options: ~ - • {width} (table) new |nvim_tree.config.view| {width} value - • {absolute} (number) set the width - • {relative} (number) increase or decrease the width +In the absence of an |nvim_tree.config| {on_attach} function, the following +defaults will be applied. - Only one option is supported, in the priority order above. - {absolute} and {relative} do nothing when {width} is a function. +You are encouraged to copy these to your {on_attach} function. >lua -tree.change_root({path}) *nvim-tree-api.tree.change_root()* - Change the tree's root to a path. + local api = require("nvim-tree.api") - Parameters: ~ - • {path} (string) absolute or relative path + local function opts(desc) + return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true } + end - *nvim-tree-api.tree.change_root_to_node()* -tree.change_root_to_node({node}) - Change the tree's root to a folder node or the parent of a file node. + -- BEGIN_ON_ATTACH_DEFAULT + vim.keymap.set("n", "", api.tree.change_root_to_node, opts("CD")) + vim.keymap.set("n", "", api.node.open.replace_tree_buffer, opts("Open: In Place")) + vim.keymap.set("n", "", api.node.show_info_popup, opts("Info")) + vim.keymap.set("n", "", api.fs.rename_sub, opts("Rename: Omit Filename")) + vim.keymap.set("n", "", api.node.open.tab, opts("Open: New Tab")) + vim.keymap.set("n", "", api.node.open.vertical, opts("Open: Vertical Split")) + vim.keymap.set("n", "", api.node.open.horizontal, opts("Open: Horizontal Split")) + vim.keymap.set("n", "", api.node.navigate.parent_close, opts("Close Directory")) + vim.keymap.set("n", "", api.node.open.edit, opts("Open")) + vim.keymap.set("n", "", api.fs.remove, opts("Delete")) + vim.keymap.set("n", "", api.node.open.preview, opts("Open Preview")) + vim.keymap.set("n", ">", api.node.navigate.sibling.next, opts("Next Sibling")) + vim.keymap.set("n", "<", api.node.navigate.sibling.prev, opts("Previous Sibling")) + vim.keymap.set("n", ".", api.node.run.cmd, opts("Run Command")) + vim.keymap.set("n", "-", api.tree.change_root_to_parent, opts("Up")) + vim.keymap.set("n", "a", api.fs.create, opts("Create File Or Directory")) + vim.keymap.set("n", "bd", api.marks.bulk.delete, opts("Delete Bookmarked")) + vim.keymap.set("n", "bt", api.marks.bulk.trash, opts("Trash Bookmarked")) + vim.keymap.set("n", "bmv", api.marks.bulk.move, opts("Move Bookmarked")) + vim.keymap.set("n", "B", api.filter.no_buffer.toggle, opts("Toggle Filter: No Buffer")) + vim.keymap.set("n", "c", api.fs.copy.node, opts("Copy")) + vim.keymap.set("n", "C", api.filter.git.clean.toggle, opts("Toggle Filter: Git Clean")) + vim.keymap.set("n", "[c", api.node.navigate.git.prev, opts("Prev Git")) + vim.keymap.set("n", "]c", api.node.navigate.git.next, opts("Next Git")) + vim.keymap.set("n", "d", api.fs.remove, opts("Delete")) + vim.keymap.set("n", "D", api.fs.trash, opts("Trash")) + vim.keymap.set("n", "E", api.tree.expand_all, opts("Expand All")) + vim.keymap.set("n", "e", api.fs.rename_basename, opts("Rename: Basename")) + vim.keymap.set("n", "]e", api.node.navigate.diagnostics.next, opts("Next Diagnostic")) + vim.keymap.set("n", "[e", api.node.navigate.diagnostics.prev, opts("Prev Diagnostic")) + vim.keymap.set("n", "F", api.filter.live.clear, opts("Live Filter: Clear")) + vim.keymap.set("n", "f", api.filter.live.start, opts("Live Filter: Start")) + vim.keymap.set("n", "g?", api.tree.toggle_help, opts("Help")) + vim.keymap.set("n", "gy", api.fs.copy.absolute_path, opts("Copy Absolute Path")) + vim.keymap.set("n", "ge", api.fs.copy.basename, opts("Copy Basename")) + vim.keymap.set("n", "H", api.filter.dotfiles.toggle, opts("Toggle Filter: Dotfiles")) + vim.keymap.set("n", "I", api.filter.git.ignored.toggle, opts("Toggle Filter: Git Ignored")) + vim.keymap.set("n", "J", api.node.navigate.sibling.last, opts("Last Sibling")) + vim.keymap.set("n", "K", api.node.navigate.sibling.first, opts("First Sibling")) + vim.keymap.set("n", "L", api.node.open.toggle_group_empty, opts("Toggle Group Empty")) + vim.keymap.set("n", "M", api.filter.no_bookmark.toggle, opts("Toggle Filter: No Bookmark")) + vim.keymap.set("n", "m", api.marks.toggle, opts("Toggle Bookmark")) + vim.keymap.set("n", "o", api.node.open.edit, opts("Open")) + vim.keymap.set("n", "O", api.node.open.no_window_picker, opts("Open: No Window Picker")) + vim.keymap.set("n", "p", api.fs.paste, opts("Paste")) + vim.keymap.set("n", "P", api.node.navigate.parent, opts("Parent Directory")) + vim.keymap.set("n", "q", api.tree.close, opts("Close")) + vim.keymap.set("n", "r", api.fs.rename, opts("Rename")) + vim.keymap.set("n", "R", api.tree.reload, opts("Refresh")) + vim.keymap.set("n", "s", api.node.run.system, opts("Run System")) + vim.keymap.set("n", "S", api.tree.search_node, opts("Search")) + vim.keymap.set("n", "u", api.fs.rename_full, opts("Rename: Full Path")) + vim.keymap.set("n", "U", api.filter.custom.toggle, opts("Toggle Filter: Custom")) + vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse All")) + vim.keymap.set("n", "x", api.fs.cut, opts("Cut")) + vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name")) + vim.keymap.set("n", "Y", api.fs.copy.relative_path, opts("Copy Relative Path")) + vim.keymap.set("n", "<2-LeftMouse>", api.node.open.edit, opts("Open")) + vim.keymap.set("n", "<2-RightMouse>", api.tree.change_root_to_node, opts("CD")) + -- END_ON_ATTACH_DEFAULT +< +Alternatively, you may apply these default mappings from your +|nvim_tree.config| {on_attach} via |nvim_tree.api.map.on_attach.default()| e.g. >lua - Parameters: ~ - • {node} (Node) folder or file + local function my_on_attach(bufnr) + local api = require("nvim-tree.api") - *nvim-tree-api.tree.change_root_to_parent()* -tree.change_root_to_parent({node}) - Change the tree's root to the parent of a node. + local function opts(desc) + return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true } + end - Parameters: ~ - • {node} (Node) folder or file + api.map.on_attach.default.on_attach_default(bufnr) -tree.get_node_under_cursor() *nvim-tree-api.tree.get_node_under_cursor()* - Retrieve the currently focused node. + -- your removals and mappings go here + end +< - Return: ~ - node or nil if tree is not visible +============================================================================== +Icons And Highlighting *nvim-tree-icons-highlighting* -tree.get_nodes() *nvim-tree-api.tree.get_nodes()* - Retrieve a hierarchical list of all the nodes. This is a cloned list for - reference purposes only and should not be passed into other API functions. +Icons may be displayed before files and directories. - Return: ~ - table of nodes +Additional icons and highlighting may be displayed to indicate various states +for files and and directories. -tree.find_file({opts}) *nvim-tree-api.tree.find_file()* - Find and focus a file or folder in the tree. Finds current buffer unless - otherwise specified. +Highlighting is additive, with higher precedence overriding lower. - Parameters: ~ - • {opts} (table) optional parameters +|nvim_tree.config.renderer| {decorators} controls which highlighting is +applied and its precedence. See |nvim-tree-decorators| for information on +creating custom decorators. +< +`ICON` + Enable via |nvim_tree.config.renderer.icons.show - Options: ~ - • {buf} (string|number) absolute/relative path OR bufnr to find - • {open} (boolean) open the tree if necessary - • {current_window} (boolean) requires {open}, open in the current window - • {winid} (number) open the tree in the specified |winid|, - overrides {current_window} - • {update_root} (boolean) see |nvim_tree.config.update_focused_file| {update_root} - • {focus} (boolean) focus the tree +`REQUIRES` + Feature must be enabled to show icons and highlighting. -tree.search_node() *nvim-tree-api.tree.search_node()* - Open the search dialogue as per the search_node action. +`PLACEMENT` *nvim_tree.config.renderer.icons.placement* + Where to place the icon: |nvim_tree.config.renderer.icons| {_placement} + • `before`: before file/folder, after the file/folders icons + • `after`: after file/folder + • `signcolumn`: far left, requires |nvim_tree.config.view| {signcolumn}. + • `right_align`: far right -tree.collapse_all({opts}) *nvim-tree-api.tree.collapse_all()* - Collapse the tree. +`HIGHLIGHT` *nvim_tree.config.renderer.highlight* + What should be highlighted: |nvim_tree.config.renderer| {highlight_} + • `none`: no highlighting + • `icon`: icon only + • `name`: name only + • `all`: icon and name - Parameters: ~ - • {opts} (table) optional parameters +`DEVICONS` + Glyphs and their colors will be overridden by optional plugin: + `nvim-tree/nvim-web-devicons` |nvim_tree.config.renderer.icons.web_devicons| - Options: ~ - • {keep_buffers} (boolean) do not collapse nodes with open buffers. +`GLYPHS` + Icon glyphs definitions. -tree.expand_all({node}, {opts}) *nvim-tree-api.tree.expand_all()* - Recursively expand all nodes under the tree root or specified folder. +`GROUPS` + Applicable highlight groups: |nvim-tree-highlight-groups| - Parameters: ~ - • {node} (Node|nil) folder - • {opts} (ApiTreeExpandOpts) optional parameters +Some defaults noted. In ascending order of default highlight precedence: - Options: ~ - • {expand_until} ((fun(expansion_count: integer, node: Node?): boolean)?) - Return true if {node} should be expanded. - {expansion_count} is the total number of folders expanded. +`WHAT ICON REQUIRES PLACEMENT HIGHLIGHT GLYPHS DEVICONS GROUPS` +File Icon {file} Y - - - |nvim_tree.config.renderer.icons.glyphs| {default} Y `NvimTreeNormal`, `NvimTreeFileIcon` +Folder Icon {folder} Y - - - |nvim_tree.config.renderer.icons.glyphs.folder| Y `NvimTree*FolderName`, `NvimTree*FolderIcon` +Git Status {git} Y |nvim_tree.config.git| {git_placement} `"before"` {highlight_git} `"none"` |nvim_tree.config.renderer.icons.glyphs.git| N `NvimTreeGit*` +|bufloaded()| - - - {highlight_opened_files}`"none"` - N ` NvimTreeOpened*` +Dotfiles {hidden} N - {hidden_placement} `"after"` {highlight_hidden} `"none"` |nvim_tree.config.renderer.icons.glyphs| {hidden} N `NvimTreeHidden*` +|'modified'| {modified} Y |nvim_tree.config.modified| {modified_placement} `"after"` {highlight_modified} `"none"` |nvim_tree.config.renderer.icons.glyphs| {modified} N `NvimTreeModified*` +Bookmarked {bookmarks} Y - {bookmarks_placement} `"signcolumn"` {highlight_bookmarks} `"none"` |nvim_tree.config.renderer.icons.glyphs| {bookmark} N `NvimTreeBookmark*` +Diag Status {diagnostics}Y |nvim_tree.config.diagnostics| {diagnostics_placement}`"signcolumn"` {highlight_diagnostics} `"none" ` |nvim_tree.config.diagnostics.icons| N `NvimTreeDiagnostic*` +Cut/Copied - - - {highlight_clipboard} `"name"` - N `NvimTreeCutHL`, `NvimTreeCopiedHL` - *nvim-tree-api.tree.toggle_enable_filters()* -tree.toggle_enable_filters() - Toggle |nvim_tree.config.filters| {enable} all filters. - *nvim-tree-api.tree.toggle_gitignore_filter()* -tree.toggle_gitignore_filter() - Toggle |nvim_tree.config.filters| {git_ignored} filter. +============================================================================== +Highlight Groups *nvim-tree-highlight-groups* - *nvim-tree-api.tree.toggle_git_clean_filter()* -tree.toggle_git_clean_filter() - Toggle |nvim_tree.config.filters| {git_clean} filter. +All the following highlight groups can be configured by hand. Aside from +`NvimTreeWindowPicker`, it is not advised to colorize the background of these +groups. - *nvim-tree-api.tree.toggle_no_buffer_filter()* -tree.toggle_no_buffer_filter() - Toggle |nvim_tree.config.filters| {no_buffer} filter. +Example |:highlight| >vim + :hi NvimTreeSymlink guifg=blue gui=bold,underline +< +It is recommended to enable |'termguicolors'| for the more pleasant 24-bit +colours. - *nvim-tree-api.tree.toggle_no_bookmark_filter()* -tree.toggle_no_bookmark_filter() - Toggle |nvim_tree.config.filters| {no_bookmark} filter. +To view the nvim-tree highlight groups run |:NvimTreeHiTest| - *nvim-tree-api.tree.toggle_custom_filter()* -tree.toggle_custom_filter() - Toggle |nvim_tree.config.filters| {custom} filter. +To view all active highlight groups run `:so $VIMRUNTIME/syntax/hitest.vim` +as per |:highlight| - *nvim-tree-api.tree.toggle_hidden_filter()* -tree.toggle_hidden_filter() - Toggle |nvim_tree.config.filters| {dotfiles} filter. +The `*HL` groups are additive as per |nvim_tree.config.renderer| precedence. +Only present attributes will clobber each other. +In this example a modified, opened file will have magenta text, with cyan +undercurl: >vim + :hi NvimTreeOpenedHL guifg=magenta guisp=red gui=underline + :hi NvimTreeModifiedFileHL guisp=cyan gui=undercurl +< +To prevent usage of a highlight: -tree.toggle_help() *nvim-tree-api.tree.toggle_help()* - Toggle help view. +- Before setup: link the group to `Normal` e.g. >vim + :hi NvimTreeExecFile Normal +< +- After setup: link it to `NONE`, to override the default link e.g. >lua + :hi! link NvimTreeExecFile NONE +< +============================================================================== +Highlight Groups: Default *nvim-tree-highlight-groups-default* -tree.is_tree_buf({bufnr}) *nvim-tree-api.tree.is_tree_buf()* - Checks if a buffer is an nvim-tree. +|:highlight-link| `default` or |:highlight-default| define the groups on setup: - Parameters: ~ - • {bufnr} (number|nil) buffer handle, 0 or nil for current buffer +Standard: > + NvimTreeNormal Normal + NvimTreeNormalFloat NormalFloat + NvimTreeNormalNC NormalFloat - Return: ~ - (boolean) buffer is an nvim-tree buffer + NvimTreeLineNr LineNr + NvimTreeWinSeparator WinSeparator + NvimTreeEndOfBuffer EndOfBuffer + NvimTreePopup Normal + NvimTreeSignColumn NvimTreeNormal -tree.is_visible({opts}) *nvim-tree-api.tree.is_visible()* - Checks if nvim-tree is visible on the current, specified or any tab. + NvimTreeCursorColumn CursorColumn + NvimTreeCursorLine CursorLine + NvimTreeCursorLineNr CursorLineNr - Parameters: ~ - • {opts} (table) optional parameters + NvimTreeStatusLine StatusLine + NvimTreeStatusLineNC StatusLineNC +< +File Text: > + NvimTreeExecFile SpellCap + NvimTreeImageFile SpellCap + NvimTreeSpecialFile SpellCap + NvimTreeSymlink SpellCap +< +Folder Text: > + NvimTreeRootFolder Title + NvimTreeFolderName Directory + NvimTreeEmptyFolderName Directory + NvimTreeOpenedFolderName Directory + NvimTreeSymlinkFolderName Directory +< +File Icons: > + NvimTreeFileIcon NvimTreeNormal + NvimTreeSymlinkIcon NvimTreeNormal +< +Folder Icons: > + NvimTreeFolderIcon guifg=#8094b4 ctermfg=Blue + NvimTreeOpenedFolderIcon NvimTreeFolderIcon + NvimTreeClosedFolderIcon NvimTreeFolderIcon + NvimTreeFolderArrowClosed NvimTreeIndentMarker + NvimTreeFolderArrowOpen NvimTreeIndentMarker +< +Indent: > + NvimTreeIndentMarker NvimTreeFileIcon +< +Picker: > + NvimTreeWindowPicker guifg=#ededed guibg=#4493c8 gui=bold ctermfg=White ctermbg=Cyan +< +Live Filter: > + NvimTreeLiveFilterPrefix PreProc + NvimTreeLiveFilterValue ModeMsg +< +Clipboard: > + NvimTreeCopiedHL SpellRare + NvimTreeCutHL SpellBad +< +Bookmarks: > + NvimTreeBookmarkIcon NvimTreeFolderIcon + NvimTreeBookmarkHL SpellLocal +< +Modified: > + NvimTreeModifiedIcon Type + NvimTreeModifiedFileHL NvimTreeModifiedIcon + NvimTreeModifiedFolderHL NvimTreeModifiedIcon - Options: ~ - • {tabpage} (number) as per |nvim_get_current_tabpage()| - • {any_tabpage} (boolean) visible on any tab, default false +Hidden: > + NvimTreeModifiedIcon Conceal + NvimTreeModifiedFileHL NvimTreeHiddenIcon + NvimTreeModifiedFolderHL NvimTreeHiddenFileHL +< +Hidden Display: > + NvimTreeHiddenDisplay Conceal +< +Opened: > + NvimTreeOpenedHL Special +< +Git Icon: > + NvimTreeGitDeletedIcon Statement + NvimTreeGitDirtyIcon Statement + NvimTreeGitIgnoredIcon Comment + NvimTreeGitMergeIcon Constant + NvimTreeGitNewIcon PreProc + NvimTreeGitRenamedIcon PreProc + NvimTreeGitStagedIcon Constant +< +Git File File Highlight: > + NvimTreeGitFileDeletedHL NvimTreeGitDeletedIcon + NvimTreeGitFileDirtyHL NvimTreeGitDirtyIcon + NvimTreeGitFileIgnoredHL NvimTreeGitIgnoredIcon + NvimTreeGitFileMergeHL NvimTreeGitMergeIcon + NvimTreeGitFileNewHL NvimTreeGitNewIcon + NvimTreeGitFileRenamedHL NvimTreeGitRenamedIcon + NvimTreeGitFileStagedHL NvimTreeGitStagedIcon +< +Git Folder Folder Highlight: > + NvimTreeGitFolderDeletedHL NvimTreeGitFileDeletedHL + NvimTreeGitFolderDirtyHL NvimTreeGitFileDirtyHL + NvimTreeGitFolderIgnoredHL NvimTreeGitFileIgnoredHL + NvimTreeGitFolderMergeHL NvimTreeGitFileMergeHL + NvimTreeGitFolderNewHL NvimTreeGitFileNewHL + NvimTreeGitFolderRenamedHL NvimTreeGitFileRenamedHL + NvimTreeGitFolderStagedHL NvimTreeGitFileStagedHL +< +Diagnostics Icon: > + NvimTreeDiagnosticErrorIcon DiagnosticError + NvimTreeDiagnosticWarnIcon DiagnosticWarn + NvimTreeDiagnosticInfoIcon DiagnosticInfo + NvimTreeDiagnosticHintIcon DiagnosticHint +< +Diagnostics File Highlight: > + NvimTreeDiagnosticErrorFileHL DiagnosticUnderlineError + NvimTreeDiagnosticWarnFileHL DiagnosticUnderlineWarn + NvimTreeDiagnosticInfoFileHL DiagnosticUnderlineInfo + NvimTreeDiagnosticHintFileHL DiagnosticUnderlineHint +< +Diagnostics Folder Highlight: > + NvimTreeDiagnosticErrorFolderHL NvimTreeDiagnosticErrorFileHL + NvimTreeDiagnosticWarnFolderHL NvimTreeDiagnosticWarnFileHL + NvimTreeDiagnosticInfoFolderHL NvimTreeDiagnosticInfoFileHL + NvimTreeDiagnosticHintFolderHL NvimTreeDiagnosticHintFileHL +< +============================================================================== +Events *nvim-tree-events* - Return: ~ - (boolean) nvim-tree is visible +nvim-tree will dispatch events whenever an action is made. These events can be +subscribed to through handler functions. This allows for even further +customization of nvim-tree. -tree.winid({opts}) *nvim-tree-api.tree.winid()* - Retrieve the winid of the open tree. +A handler for an event is just a function which receives one argument, the +payload of the event. The payload is different for each event type. Refer +to |nvim_tree_registering_handlers| for more information. - Parameters: ~ - • {opts} (table) optional parameters +*nvim_tree_registering_handlers* - Options: ~ - • {tabpage} (number|nil) tabpage, 0 or nil for current, default nil +Handlers are registered by calling |nvim_tree.api.events.subscribe()| function +with an |nvim_tree_events_kind|. - Return: ~ - (number) winid or nil if tree is not visible +e.g. handler for node renamed: >lua -============================================================================== -API: File System *nvim-tree-api.fs* + local api = require("nvim-tree.api") + local Event = api.events.Event -fs.create({node}) *nvim-tree-api.fs.create()* - Prompt to create a file or directory. Use a trailing `/` for a directory. - Multiple directories/files may be created e.g. `foo/bar/baz` + api.events.subscribe(Event.NodeRenamed, function(data) + print("Node renamed from " .. data.old_name .. " to " .. data.new_name) + end) +< +*nvim_tree_events_kind* - Parameters: ~ - • {node} (Node|nil) parent, uses the parent of a file. +- Event.Ready + When NvimTree has been initialized. + • Note: Handler takes no parameter. -fs.remove({node}) *nvim-tree-api.fs.remove()* - Delete a file or folder from the file system. +- Event.TreePreOpen + Invoked before the window and buffer for NvimTree are created + or opened. Before `Event.TreeOpen` + • Note: Handler takes no parameter. - Parameters: ~ - • {node} (Node|nil) file or folder +- Event.TreeOpen + Invoked after the NvimTree is opened. + • Note: Handler takes no parameter. -fs.trash({node}) *nvim-tree-api.fs.trash()* - Trash a file or folder as per |nvim_tree.config.trash| +- Event.TreeClose + Invoked after the NvimTree is closed, but before the window is + closed. Dispatched on |WinClosed| event for NvimTree window. + • Note: Handler takes no parameter. - Parameters: ~ - • {node} (Node|nil) file or folder +- Event.Resize - When NvimTree is resized. + handler parameters: ~ + size: `number` size of the view in columns. -fs.rename_node({node}) *nvim-tree-api.fs.rename_node()* - Prompt to rename a file or folder. +- Event.WillRenameNode + • Note: A node can either be a file or a directory. + handler parameters: ~ + {old_name} `{string}` Absolute path to the old node location. + {new_name} `{string}` Absolute path to the new node location. - Parameters: ~ - • {node} (Node|nil) file or folder +- Event.NodeRenamed + • Note: A node can either be a file or a directory. + handler parameters: ~ + {old_name} `{string}` Absolute path to the old node location. + {new_name} `{string}` Absolute path to the new node location. -fs.rename({node}) *nvim-tree-api.fs.rename()* - Prompt to rename a file or folder by name. +- Event.FileCreated + handler parameters: ~ + {fname} `{string}` Absolute path to the created file - Parameters: ~ - • {node} (Node|nil) file or folder +- Event.WillCreateFile + handler parameters: ~ + {fname} `{string}` Absolute path to the file to be + created -fs.rename_basename({node}) *nvim-tree-api.fs.rename_basename()* - Prompt to rename a file or folder by name with extension omitted. +- Event.FileRemoved + handler parameters: ~ + {fname} `{string}` Absolute path to the removed file. - Parameters: ~ - • {node} (Node|nil) file or folder +- Event.WillRemoveFile + handler parameters: ~ + {fname} `{string}` Absolute path to the file to be + removed -fs.rename_sub({node}) *nvim-tree-api.fs.rename_sub()* - Prompt to rename a file or folder by absolute path with name omitted. +- Event.FolderCreated + handler parameters: ~ + {folder_name} `{string}` Absolute path to the created folder. - Parameters: ~ - • {node} (Node|nil) file or folder +- Event.FolderRemoved + handler parameters: ~ + {folder_name} `{string}` Absolute path to the removed folder. -fs.rename_full({node}) *nvim-tree-api.fs.rename_full()* - Prompt to rename a file or folder by absolute path. +- Event.TreeAttachedPost + Invoked after the tree's buffer has been created and mappings + have been applied: |nvim-tree-mappings| or |nvim_tree.config| {on_attach} + handler parameters: ~ + {buf} `{number} `API buffer handle (buffer number) - Parameters: ~ - • {node} (Node|nil) file or folder +- Event.TreeRendered + Invoked every time the tree is redrawn. Normally this event + happens after `Event.TreeOpen` except that handlers of this + one will have access to the tree buffer populated with the + final content. + handler parameters: ~ + {bufnr} `{number} `API buffer handle (buffer number) + {winnr} `{number} `API window handle (window number) -fs.cut({node}) *nvim-tree-api.fs.cut()* - Cut a file or folder to the nvim-tree clipboard. +*nvim_tree_events_startup* - Parameters: ~ - • {node} (Node|nil) file or folder +There are two special startup events in the form of User autocommands: -fs.paste({node}) *nvim-tree-api.fs.paste()* - Paste a file or folder from the nvim-tree clipboard. +`NvimTreeRequired` first `require("nvim-tree")` +`NvimTreeSetup` `setup({})` completed - Parameters: ~ - • {node} (Node|nil) destination folder, uses the parent of a file. +Immediately before firing: a global variable of the same name will be set to a +value of 1. -fs.copy.node({node}) *nvim-tree-api.fs.copy.node()* - Copy a file or folder from the nvim-tree clipboard. +Example subscription: >lua - Parameters: ~ - • {node} (Node|nil) file or folder + vim.api.nvim_create_autocmd("User", { + pattern = "NvimTreeRequired", + callback = function(data) + --- + end, + }) +< +============================================================================== +Prompts *nvim-tree-prompts* -fs.copy.absolute_path({node}) *nvim-tree-api.fs.copy.absolute_path()* - Copy the absolute path of a file or folder to the system clipboard. +Some NvimTree actions use the builtin |vim.ui.select()| prompt API for +confirmations when the |nvim_tree.config| {select_prompts} option is set. - Parameters: ~ - • {node} (Node|nil) file or folder +The API accepts the optional `kind` key as part of the {opts} parameter, which +can can be used to identify the type of prompt, to allow user side +configurations for different types of prompts. -fs.copy.basename({node}) *nvim-tree-api.fs.copy.basename()* - Copy the name of a file or folder with extension omitted to the system - clipboard. +- `nvimtree_overwrite_rename` + overwrite or rename during |nvim_tree.api.fs.paste()| - Parameters: ~ - • {node} (Node|nil) file or folder - -fs.copy.filename({node}) *nvim-tree-api.fs.copy.filename()* - Copy the name of a file or folder to the system clipboard. - - Parameters: ~ - • {node} (Node|nil) file or folder - -fs.copy.relative_path({node}) *nvim-tree-api.fs.copy.relative_path()* - Copy the path of a file or folder relative to the tree root to the system - clipboard. +- `nvimtree_remove` + delete during |nvim_tree.api.fs.remove()| - Parameters: ~ - • {node} (Node|nil) file or folder +- `nvimtree_trash` + send to trash during |nvim_tree.api.fs.trash()| -fs.clear_clipboard() *nvim-tree-api.fs.clear_clipboard()* - Clear the nvim-tree clipboard. +- `nvimtree_bulk_delete` + delete all bookmarked during |nvim_tree.api.marks.bulk.delete()| -fs.print_clipboard() *nvim-tree-api.fs.print_clipboard()* - Print the contents of the nvim-tree clipboard. +- `nvimtree_bulk_trash` + send all bookmarked to trash during |nvim_tree.api.marks.bulk.trash()| ============================================================================== -API: Node *nvim-tree-api.node* +Decorators *nvim-tree-decorators* -node.open.edit({node}, {opts}) *nvim-tree-api.node.open.edit()* - File: open as per |nvim_tree.config.actions.open_file| - Folder: expand or collapse - Root: change directory up +Highlighting and icons for nodes are provided by Decorators. You may provide +your own in addition to the builtin decorators. - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters +Decorators may: +- Add icons +- Set highlight group for the name or icons +- Override node icon - Options: ~ - • {quit_on_open} (boolean) quits the tree when opening the file - • {focus} (boolean) keep focus in the tree when opening the file +Create a `nvim_tree.api.decorator.UserDecorator` class and register it with +precedence via |nvim_tree.config.renderer| {decorators} - *nvim-tree-api.node.open.replace_tree_buffer()* -node.open.replace_tree_buffer({node}) - |nvim-tree-api.node.open.edit()|, file will be opened in place: in the - nvim-tree window. +See |nvim-tree-decorator-example| - *nvim-tree-api.node.open.no_window_picker()* -node.open.no_window_picker({node}, {opts}) - |nvim-tree-api.node.open.edit()|, window picker will be bypassed. +============================================================================== +Decorators: Example *nvim-tree-decorator-example* - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters +A decorator class for nodes named "example", overridind all builtin decorators +except for Cut. - Options: ~ - • {quit_on_open} (boolean) quits the tree when opening the file - • {focus} (boolean) keep focus in the tree when opening the file +- Highlights node name with `IncSearch` +- Creates two icons `"1"` and `"2"` placed after the node name, highlighted with + `DiffAdd` and `DiffText` +- Replaces the node icon with `"N"`, highlighted with `Error ` -node.open.vertical({node}, {opts}) *nvim-tree-api.node.open.vertical()* - |nvim-tree-api.node.open.edit()|, file will be opened in a new vertical split. +Create a class file `~/.config/nvim/lua/my-decorator.lua` - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters +Require and register it during |nvim-tree-setup|: +>lua + local MyDecorator = require("my-decorator") - Options: ~ - • {quit_on_open} (boolean) quits the tree when opening the file - • {focus} (boolean) keep focus in the tree when opening the file + require("nvim-tree").setup({ + renderer = { + decorators = { + "Git", + "Open", + "Hidden", + "Modified", + "Bookmark", + "Diagnostics", + "Copied", + MyDecorator, + "Cut", + }, + }, + }) +< +Contents of `my-decorator.lua`: +>lua + ---@class (exact) MyDecorator: nvim_tree.api.decorator.UserDecorator + ---@field private my_icon1 nvim_tree.api.HighlightedString + ---@field private my_icon2 nvim_tree.api.HighlightedString + ---@field private my_icon_node nvim_tree.api.HighlightedString + ---@field private my_highlight_group string + local MyDecorator = require("nvim-tree.api").decorator.UserDecorator:extend() - *nvim-tree-api.node.open.vertical_no_picker()* -node.open.vertical_no_picker({node}, {opts}) - |nvim-tree-api.node.open.vertical()|, window picker will be bypassed. + ---Mandatory constructor :new() will be called once per tree render, with no arguments. + function MyDecorator:new() + self.enabled = true + self.highlight_range = "name" + self.icon_placement = "after" - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters + -- create your icons and highlights once, applied to every node + self.my_icon1 = { str = "1", hl = { "DiffAdd" } } + self.my_icon2 = { str = "2", hl = { "DiffText" } } + self.my_icon_node = { str = "N", hl = { "Error" } } + self.my_highlight_group = "IncSearch" - Options: ~ - • {quit_on_open} (boolean) quits the tree when opening the file - • {focus} (boolean) keep focus in the tree when opening the file + -- Define the icon signs only once + -- Only needed if you are using icon_placement = "signcolumn" + -- self:define_sign(self.my_icon1) + -- self:define_sign(self.my_icon2) + end -node.open.horizontal({node}, {opts}) *nvim-tree-api.node.open.horizontal()* - |nvim-tree-api.node.open.edit()|, file will be opened in a new horizontal split. + ---Override node icon + ---@param node nvim_tree.api.Node + ---@return nvim_tree.api.HighlightedString? icon_node + function MyDecorator:icon_node(node) + if node.name == "example" then + return self.my_icon_node + else + return nil + end + end - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters + ---Return two icons for DecoratorIconPlacement "after" + ---@param node nvim_tree.api.Node + ---@return nvim_tree.api.HighlightedString[]? icons + function MyDecorator:icons(node) + if node.name == "example" then + return { self.my_icon1, self.my_icon2, } + else + return nil + end + end - Options: ~ - • {quit_on_open} (boolean) quits the tree when opening the file - • {focus} (boolean) keep focus in the tree when opening the file + ---Exactly one highlight group for DecoratorHighlightRange "name" + ---@param node nvim_tree.api.Node + ---@return string? highlight_group + function MyDecorator:highlight_group(node) + if node.name == "example" then + return self.my_highlight_group + else + return nil + end + end - *nvim-tree-api.node.open.horizontal_no_picker()* -node.open.horizontal_no_picker({node}, {opts}) - |nvim-tree-api.node.open.horizontal()|, window picker will be bypassed. + return MyDecorator +< +============================================================================== +OS Specific Restrictions *nvim-tree-os-specific* - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters +Windows WSL and PowerShell +- Trash is synchronized +- Executable file detection is disabled as this is non-performant and can + freeze Nvim +- Some filesystem watcher error related to permissions will not be reported - Options: ~ - • {quit_on_open} (boolean) quits the tree when opening the file - • {focus} (boolean) keep focus in the tree when opening the file +Powershell +- Observed Nvim hanging after a runaway (infinite) number of events on a + single directory. See |nvim_tree.config.filesystem_watchers| {max_events} - *nvim-tree-api.node.open.toggle_group_empty()* -node.open.toggle_group_empty({node}, {opts}) - Toggle |nvim_tree.config.renderer| {group_empty} for a specific folder. - Does nothing on files. - Needs |nvim_tree.config.renderer| {group_empty} set. +============================================================================== +netrw *nvim-tree-netrw* - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters +|netrw| is a standard Nvim plugin that is enabled by default. It provides, +amongst other functionality, a file/directory browser. - Options: ~ - • {quit_on_open} (boolean) quits the tree when opening the file - • {focus} (boolean) keep focus in the tree when opening the file +It interferes with nvim-tree and the intended user experience is nvim-tree +replacing the |netrw| browser. -node.open.drop({node}) *nvim-tree-api.node.open.drop()* - Switch to window with selected file if it exists. - Open file otherwise. - See: `:h :drop`. +It is strongly recommended to disable |netrw|. As it is a bundled plugin it +must be disabled manually at the start of your `init.lua` as per |netrw-noload|: >lua - File: open file using `:drop` - Folder: expand or collapse - Root: change directory up + vim.g.loaded_netrw = 1 + vim.g.loaded_netrwPlugin = 1 +< +There are many |netrw| features beyond the file browser. If you want to +keep using |netrw| without its browser features please ensure: -node.open.tab({node}, {opts}) *nvim-tree-api.node.open.tab()* - |nvim-tree-api.node.open.edit()|, file will be opened in a new tab. +|nvim_tree.config| {disable_netrw}` = false` +|nvim_tree.config| {hijack_netrw}` = true` - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters +============================================================================== +Legacy *nvim-tree-legacy* - Options: ~ - • {quit_on_open} (boolean) quits the tree when opening the file - • {focus} (boolean) keep focus in the tree when opening the file +Breaking refactors have been made however the legacy versions will be silently +migrated and used. +There are no plans to remove this migration. - *nvim-tree-api.node.open.tab_drop()* -node.open.tab_drop({node}) - Switch to tab containing window with selected file if it exists. - Open file in new tab otherwise. +============================================================================== +Legacy: Config *nvim-tree-legacy-config* - File: open file using `tab :drop` - Folder: expand or collapse - Root: change directory up +Legacy config is translated to the current, making type and value changes as +needed. -node.open.preview({node}, {opts}) *nvim-tree-api.node.open.preview()* - |nvim-tree-api.node.open.edit()|, file buffer will have |'bufhidden'| set to `delete`. +`update_cwd` |nvim_tree.config| {sync_root_with_cwd} +`update_focused_file.update_cwd` |nvim_tree.config.update_focused_file| {update_root} +`open_on_tab` |nvim_tree.config.tab.sync| {open} +`ignore_buf_on_tab_change` |nvim_tree.config.tab.sync| {ignore} +`renderer.root_folder_modifier` |nvim_tree.config.renderer| {root_folder_label} +`update_focused_file.debounce_delay` |nvim_tree.config.view| {debounce_delay} +`trash.require_confirm` |nvim_tree.config.ui.confirm| {trash} +`view.adaptive_size` |nvim_tree.config.view| {width} +`sort_by` |nvim_tree.config.sort| {sorter} +`git.ignore` |nvim_tree.config.filters| {git_ignored} +`renderer.icons.webdev_colors` |nvim_tree.config.renderer.icons.web_devicons.file| {color} +`renderer.icons.padding` |nvim_tree.config.renderer.icons.padding| {icon} - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters +============================================================================== +Legacy: API *nvim-tree-legacy-api* - Options: ~ - • {quit_on_open} (boolean) quits the tree when opening the file - • {focus} (boolean) keep focus in the tree when opening the file +Some API functions have been refactored however the previous function will +continue to be available. - *nvim-tree-api.node.open.preview_no_picker()* -node.open.preview_no_picker({node}, {opts}) - |nvim-tree-api.node.open.edit()|, file buffer will have |'bufhidden'| set to `delete`. - window picker will be bypassed. +`api.config.mappings.get_keymap` |nvim_tree.api.map.keymap.current()| +`api.config.mappings.get_keymap_default` |nvim_tree.api.map.keymap.default()| +`api.config.mappings.default_on_attach` |nvim_tree.api.map.on_attach.default()| - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters +`api.diagnostics.hi_test` |nvim_tree.api.health.hi_test()| - Options: ~ - • {quit_on_open} (boolean) quits the tree when opening the file - • {focus} (boolean) keep focus in the tree when opening the file +`api.live_filter.start` |nvim_tree.api.filter.live.start()| +`api.live_filter.clear` |nvim_tree.api.filter.live.clear()| -node.navigate.git.next({node}) *nvim-tree-api.node.navigate.git.next()* - Navigate to the next item showing git status. +`api.tree.toggle_enable_filters` |nvim_tree.api.filter.toggle()| +`api.tree.toggle_gitignore_filter` |nvim_tree.api.filter.git.ignored.toggle()| +`api.tree.toggle_git_clean_filter` |nvim_tree.api.filter.git.clean.toggle()| +`api.tree.toggle_no_buffer_filter` |nvim_tree.api.filter.no_buffer.toggle()| +`api.tree.toggle_custom_filter` |nvim_tree.api.filter.custom.toggle()| +`api.tree.toggle_hidden_filter` |nvim_tree.api.filter.dotfiles.toggle()| +`api.tree.toggle_no_bookmark_filter` |nvim_tree.api.filter.no_bookmark.toggle()| - *nvim-tree-api.node.navigate.git.next_recursive()* -node.navigate.git.next_recursive({node}) - Alternative to |nvim-tree-api.node.navigate.git.next()| that navigates to - the next file showing git status, recursively. - Needs |nvim_tree.config.git| {show_on_dirs} set. +============================================================================== +Legacy: Highlight *nvim-tree-legacy-highlight* - *nvim-tree-api.node.navigate.git.next_skip_gitignored()* -node.navigate.git.next_skip_gitignored({node}) - Same as |nvim-tree-api.node.navigate.git.next()|, but skips gitignored files. +Legacy highlight group are still obeyed when they are defined and the current +highlight group is not, hard linking as follows: > -node.navigate.git.prev({node}) *nvim-tree-api.node.navigate.git.prev()* - Navigate to the previous item showing git status. + NvimTreeModifiedIcon NvimTreeModifiedFile + NvimTreeOpenedHL NvimTreeOpenedFile + NvimTreeBookmarkIcon NvimTreeBookmark - *nvim-tree-api.node.navigate.git.prev_recursive()* -node.navigate.git.prev_recursive({node}) - Alternative to |nvim-tree-api.node.navigate.git.prev()| that navigates to - the previous file showing git status, recursively. - Needs |nvim_tree.config.git| {show_on_dirs} set. + NvimTreeGitDeletedIcon NvimTreeGitDeleted + NvimTreeGitDirtyIcon NvimTreeGitDirty + NvimTreeGitIgnoredIcon NvimTreeGitIgnored + NvimTreeGitMergeIcon NvimTreeGitMerge + NvimTreeGitNewIcon NvimTreeGitNew + NvimTreeGitRenamedIcon NvimTreeGitRenamed + NvimTreeGitStagedIcon NvimTreeGitStaged - *nvim-tree-api.node.navigate.git.prev_skip_gitignored()* -node.navigate.git.prev_skip_gitignored({node}) - same as |nvim-tree-api.node.navigate.git.prev()|, but skips gitignored files. + NvimTreeGitFileDeletedHL NvimTreeFileDeleted + NvimTreeGitFileDirtyHL NvimTreeFileDirty + NvimTreeGitFileIgnoredHL NvimTreeFileIgnored + NvimTreeGitFileMergeHL NvimTreeFileMerge + NvimTreeGitFileNewHL NvimTreeFileNew + NvimTreeGitFileRenamedHL NvimTreeFileRenamed + NvimTreeGitFileStagedHL NvimTreeFileStaged - *nvim-tree-api.node.navigate.diagnostics.next()* -node.navigate.diagnostics.next({node}) - Navigate to the next item showing diagnostic status. + NvimTreeGitFolderDeletedHL NvimTreeFolderDeleted + NvimTreeGitFolderDirtyHL NvimTreeFolderDirty + NvimTreeGitFolderIgnoredHL NvimTreeFolderIgnored + NvimTreeGitFolderMergeHL NvimTreeFolderMerge + NvimTreeGitFolderNewHL NvimTreeFolderNew + NvimTreeGitFolderRenamedHL NvimTreeFolderRenamed + NvimTreeGitFolderStagedHL NvimTreeFolderStaged - *nvim-tree-api.node.navigate.diagnostics.next_recursive()* -node.navigate.diagnostics.next_recursive({node}) - Alternative to |nvim-tree-api.node.navigate.diagnostics.next()| that - navigates to the next file showing diagnostic status, recursively. - Needs |nvim_tree.config.diagnostics| {show_on_dirs} set. + NvimTreeLspDiagnosticsError NvimTreeDiagnosticErrorIcon + NvimTreeLspDiagnosticsWarning NvimTreeDiagnosticWarnIcon + NvimTreeLspDiagnosticsInformation NvimTreeDiagnosticInfoIcon + NvimTreeLspDiagnosticsHint NvimTreeDiagnosticHintIcon - *nvim-tree-api.node.navigate.diagnostics.prev()* -node.navigate.diagnostics.prev({node}) - Navigate to the next item showing diagnostic status. + NvimTreeLspDiagnosticsErrorText NvimTreeDiagnosticErrorFileHL + NvimTreeLspDiagnosticsWarningText NvimTreeDiagnosticWarnFileHL + NvimTreeLspDiagnosticsInformationText NvimTreeDiagnosticInfoFileHL + NvimTreeLspDiagnosticsHintText NvimTreeDiagnosticHintFileHL - *nvim-tree-api.node.navigate.diagnostics.prev_recursive()* -node.navigate.diagnostics.prev_recursive({node}) - Alternative to |nvim-tree-api.node.navigate.diagnostics.prev()| that - navigates to the previous file showing diagnostic status, recursively. - Needs |nvim_tree.config.diagnostics| {show_on_dirs} set. + NvimTreeLspDiagnosticsErrorFolderText NvimTreeDiagnosticErrorFolderHL + NvimTreeLspDiagnosticsWarningFolderText NvimTreeDiagnosticWarnFolderHL + NvimTreeLspDiagnosticsInformationFolderText NvimTreeDiagnosticInfoFolderHL + NvimTreeLspDiagnosticsHintFolderText NvimTreeDiagnosticHintFolderHL +< - *nvim-tree-api.node.navigate.opened.next()* -node.navigate.opened.next({node}) - Navigate to the next |bufloaded()| item. - See |nvim_tree.config.renderer| {highlight_opened_files} +============================================================================== +Hidden Display *nvim-tree-hidden-display* - *nvim-tree-api.node.navigate.opened.prev()* -node.navigate.opened.prev({node}) - Navigate to the previous |bufloaded()| item. - See |nvim_tree.config.renderer| {highlight_opened_files} +Show a summary of hidden files below the tree highlighted with `NvimTreeHiddenDisplay - *nvim-tree-api.node.navigate.sibling.next()* -node.navigate.sibling.next({node}) - Navigate to the next node in the current node's folder, wraps. +Configure via |nvim_tree.config.renderer| {hidden_display} - *nvim-tree-api.node.navigate.sibling.prev()* -node.navigate.sibling.prev({node}) - Navigate to the previous node in the current node's folder, wraps. + *nvim_tree.config.renderer.hidden_display* + • `none`: disabled + • `simple`: show how many hidden files are in a folder + • `all`: show how many hidden and the number of hidden files by reason + • `fun(hidden_stats: table): string`: returns a summary of hidden stats - *nvim-tree-api.node.navigate.sibling.first()* -node.navigate.sibling.first({node}) - Navigate to the first node in the current node's folder. +Example `"all"`: +If a folder has 14 hidden items for various reasons, the display might show: > + (14 total git: 5, dotfile: 9) +< +If a function is provided, it receives a table `hidden_stats` where keys are +reasons and values are the count of hidden files for that reason. - *nvim-tree-api.node.navigate.sibling.last()* -node.navigate.sibling.last({node}) - Navigate to the last node in the current node's folder. +The `hidden_stats` argument is structured as follows, where is the number +of hidden files related to the field: > + hidden_stats = { + bookmark = , + buf = , + custom = , + dotfile = , + git = , + live_filter = , + } +< +Example of function that can be passed: >lua + function(hidden_stats) + local total_count = 0 + for reason, count in pairs(hidden_stats) do + total_count = total_count + count + end - *nvim-tree-api.node.navigate.parent()* -node.navigate.parent({node}) - Navigate to the parent folder of the current node. + if total_count > 0 then + return "(" .. tostring(total_count) .. " hidden)" + end + return nil + end +< - *nvim-tree-api.node.navigate.parent_close()* -node.navigate.parent_close({node}) - |nvim-tree-api.node.navigate.parent()|, closing that folder. +============================================================================== +Config *nvim-tree-config* -node.show_info_popup({node}) *nvim-tree-api.node.show_info_popup()* - Open a popup window showing: fullpath, size, accessed, modified, created. +*nvim_tree.config* + Arguments to pass to |nvim-tree-setup|. -node.run.cmd({node}) *nvim-tree-api.node.run.cmd()* - Enter |cmdline| with the full path of the node and the cursor at the start - of the line. + When a value is not present/nil, the default will be used. -node.run.system({node}) *nvim-tree-api.node.run.system()* - Execute |nvim_tree.config.system_open| - -node.buffer.delete({node}, {opts}) *nvim-tree-api.node.buffer.delete()* - Deletes node's related buffer, if one exists. - Executes |:bdelete| or |:bdelete|! - - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters - - Options: ~ - • {force} (boolean) delete even if buffer is modified, default false - -node.buffer.wipe({node}, {opts}) *nvim-tree-api.node.buffer.wipe()* - Wipes node's related buffer, if one exists. - Executes |:bwipe| or |:bwipe|! - - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters - - Options: ~ - • {force} (boolean) wipe even if buffer is modified, default false - -node.expand({node}, {opts}) *nvim-tree-api.node.expand()* - Recursively expand all nodes under a directory or a file's parent - directory. - - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (ApiTreeExpandOpts) optional parameters + {on_attach} Runs when creating the nvim-tree buffer. Use this to set your + |nvim-tree-mappings|. When not a function, |nvim-tree-mappings-default| + will be used. - Options: ~ - • {expand_until} ((fun(expansion_count: integer, node: Node?): boolean)?) - Return true if {node} should be expanded. - {expansion_count} is the total number of folders expanded. + {hijack_cursor} keep the cursor on the first letter of the filename when + moving in the tree. -node.collapse({node}, {opts}) *nvim-tree-api.node.collapse()* - Collapse the tree under a directory or a file's parent directory. + {auto_reload_on_write} reload the explorer every time a buffer is written + to. - Parameters: ~ - • {node} (Node|nil) file or folder - • {opts} (table) optional parameters + {disable_netrw} completely disables |netrw|, see |nvim-tree-netrw| for + details. It is strongly advised to eagerly disable netrw, due to race + conditions at vim startup. - Options: ~ - • {keep_buffers} (boolean) do not collapse nodes with open buffers. + {hijack_netrw} hijacks netrw windows, ignored when {disable_netrw}. -============================================================================== -API: Git *nvim-tree-api.git* + {hijack_unnamed_buffer_when_opening} opens in place of the unnamed buffer + if it's empty. -git.reload() *nvim-tree-api.git.reload()* - Update the git status of the entire tree. + {root_dirs} preferred root directories, requires + |nvim_tree.config.update_focused_file.update_root|. -============================================================================== -API: Events *nvim-tree-api.events* + {prefer_startup_root} prefer startup root directory when updating root + directory of the tree. Requires + |nvim_tree.config.update_focused_file.update_root|. - *nvim-tree-api.events.subscribe()* -events.subscribe({event_type}, {callback}) - Register a handler for an event, see |nvim-tree-events| + {sync_root_with_cwd} changes the tree root directory on |DirChanged| and + refreshes the tree. - Parameters: ~ - • {event_type} (string) |nvim-tree-api.events.Event| - • {callback} (function) see |nvim_tree_events_kind| for parameters + {reload_on_bufenter} automatically reloads the tree on |BufEnter| + nvim-tree. -events.Event *nvim-tree-api.events.Event* - String enum: |nvim_tree_events_kind| + {respect_buf_cwd} changes the |current-directory| of nvim-tree to that of + new buffer's when opening nvim-tree. + {select_prompts} uses |vim.ui.select()| style prompts. Necessary when + using a UI prompt decorator such as dressing.nvim or + telescope-ui-select.nvim -============================================================================== -API: Live Filter *nvim-tree-api.live_filter* + Fields: ~ + • {on_attach}? (`"default"|(fun(bufnr: integer))`) + (default: `default`) + • {hijack_cursor}? (`boolean`) (default: `false`) + • {auto_reload_on_write}? (`boolean`) (default: `true`) + • {disable_netrw}? (`boolean`) (default: `false`) + • {hijack_netrw}? (`boolean`) (default: `true`) + • {hijack_unnamed_buffer_when_opening}? (`boolean`) (default: `false`) + • {root_dirs}? (`string[]`) (default: `{}`) + • {prefer_startup_root}? (`boolean`) (default: `false`) + • {sync_root_with_cwd}? (`boolean`) (default: `false`) + • {reload_on_bufenter}? (`boolean`) (default: `false`) + • {respect_buf_cwd}? (`boolean`) (default: `false`) + • {select_prompts}? (`boolean`) (default: `false`) + • {sort}? (`nvim_tree.config.sort`) + |nvim_tree.config.sort| + • {view}? (`nvim_tree.config.view`) + |nvim_tree.config.view| + • {renderer}? (`nvim_tree.config.renderer`) + |nvim_tree.config.renderer| + • {hijack_directories}? (`nvim_tree.config.hijack_directories`) + |nvim_tree.config.hijack_directories| + • {update_focused_file}? (`nvim_tree.config.update_focused_file`) + |nvim_tree.config.update_focused_file| + • {system_open}? (`nvim_tree.config.system_open`) + |nvim_tree.config.system_open| + • {git}? (`nvim_tree.config.git`) + |nvim_tree.config.git| + • {diagnostics}? (`nvim_tree.config.diagnostics`) + |nvim_tree.config.diagnostics| + • {modified}? (`nvim_tree.config.modified`) + |nvim_tree.config.modified| + • {filters}? (`nvim_tree.config.filters`) + |nvim_tree.config.filters| + • {live_filter}? (`nvim_tree.config.live_filter`) + |nvim_tree.config.live_filter| + • {filesystem_watchers}? (`nvim_tree.config.filesystem_watchers`) + |nvim_tree.config.filesystem_watchers| + • {actions}? (`nvim_tree.config.actions`) + |nvim_tree.config.actions| + • {trash}? (`nvim_tree.config.trash`) + |nvim_tree.config.trash| + • {tab}? (`nvim_tree.config.tab`) + |nvim_tree.config.tab| + • {bookmarks}? (`nvim_tree.config.bookmarks`) + |nvim_tree.config.bookmarks| + • {notify}? (`nvim_tree.config.notify`) + |nvim_tree.config.notify| + • {help}? (`nvim_tree.config.help`) + |nvim_tree.config.help| + • {ui}? (`nvim_tree.config.ui`) + |nvim_tree.config.ui| + • {experimental}? (`nvim_tree.config.experimental`) + |nvim_tree.config.experimental| + • {log}? (`nvim_tree.config.log`) + |nvim_tree.config.log| -live_filter.start() *nvim-tree-api.live_filter.start()* - Enter |nvim-tree-api.live_filter| mode. - Opens an input window with |filetype| `"NvimTreeFilter"` -live_filter.clear() *nvim-tree-api.live_filter.clear()* - Exit |nvim-tree-api.live_filter| mode. ============================================================================== -API: Marks *nvim-tree-api.marks* - -marks.get({node}) *nvim-tree-api.marks.get()* - Return the node if it is marked. - - Parameters: ~ - • {node} (Node) folder or file - -marks.list() *nvim-tree-api.marks.list()* - Retrieve all marked nodes. - - Return: ~ - (table) marked nodes - -marks.toggle({node}) *nvim-tree-api.marks.toggle()* - Toggle node mark. +Config: sort *nvim-tree-config-sort* - Parameters: ~ - • {node} (Node) folder or file +*nvim_tree.config.sort* + Sort files within a directory. -marks.clear() *nvim-tree-api.marks.clear()* - Clear all marks. + {sorter} presets *nvim_tree.config.sort.Sorter* + • `"name"` + • `"case_sensitive"` name + • `"modification_time"` + • `"extension"` uses all suffixes e.g. `foo.tar.gz` -> `.tar.gz` + • `"suffix"` uses the last e.g. `foo.tar.gz` -> `.gz` + • `"filetype"` |filetype| -marks.bulk.delete() *nvim-tree-api.marks.bulk.delete()* - Delete all marked. Optionally prompts. + {sorter} may be a function that is passed a list of `nvim_tree.api.Node` + to be sorted in place e.g. >lua -marks.bulk.trash() *nvim-tree-api.marks.bulk.trash()* - Trash all marked. Optionally prompts. + ---Sort by name length + ---@param nodes nvim_tree.api.Node[] + ---@return nvim_tree.config.sort.Sorter? + local sorter = function(nodes) + table.sort(nodes, function(a, b) + return #a.name < #b.name + end) + end +< -marks.bulk.move() *nvim-tree-api.marks.bulk.move()* - Prompts for a directory to move all marked nodes into. + {sorter} may be a function that returns a |nvim_tree.config.sort.Sorter| -marks.navigate.next() *nvim-tree-api.marks.navigate.next()* - Navigate to the next marked node, wraps. - Opens files as per |nvim_tree.config.actions.open_file| - Works best with |nvim_tree.config.update_focused_file| enabled. + Fields: ~ + • {sorter}? (`nvim_tree.config.sort.Sorter|(fun(nodes: nvim_tree.api.Node[]): nvim_tree.config.sort.Sorter?)`) + (default: `"name"`) + • {folders_first}? (`boolean`, default: `true`) Sort folders before + files. Has no effect when {sorter} is a function. + • {files_first}? (`boolean`, default: `false`) Sort files before + folders. Has no effect when {sorter} is a function. + Overrides {folders_first}. -marks.navigate.prev() *nvim-tree-api.marks.navigate.prev()* - As per |nvim-tree-api.marks.navigate.next()| -marks.navigate.select() *nvim-tree-api.marks.navigate.select()* - Prompts for selection of a marked node, sorted by absolute paths. - A folder will be focused, a file will be opened. ============================================================================== -API: Config *nvim-tree-api.config* +Config: view *nvim-tree-config-view* - *nvim-tree-api.config.mappings.default_on_attach()* -config.mappings.default_on_attach({bufnr}) - Set all |nvim-tree-mappings-default|. Call from your |nvim_tree.config| {on_attach} +*nvim_tree.config.view* + Configures the dimensions and appearance of the nvim-tree window. - Parameters: ~ - • {bufnr} (number) nvim-tree buffer number passed to |nvim_tree.config| {on_attach} + The window is "docked" at the left by default, however may be configured + to float: |nvim_tree.config.view.float| - *nvim-tree-api.config.mappings.get_keymap()* -config.mappings.get_keymap() - Retrieves all buffer local mappings for nvim-tree. - These are the mappings that are applied by |nvim_tree.config| {on_attach}, which - may include default mappings. + {width} can be a |nvim_tree.config.view.width.spec| for static control or + a |nvim_tree.config.view.width| for fully dynamic control based on longest + line. - Return: ~ - (table) as per |nvim_buf_get_keymap()| + *nvim_tree.config.view.width.spec* + • `string`: `x%` string e.g. `30%` + • `integer`: number of columns + • `function`: returns one of the above - *nvim-tree-api.config.mappings.get_keymap_default()* -config.mappings.get_keymap_default() - Retrieves the buffer local mappings for nvim-tree that are applied by - |nvim-tree-api.config.mappings.default_on_attach()| + Fields: ~ + • {centralize_selection}? (`boolean`, default: `false`) When + entering nvim-tree, reposition the + view so that the current node is + initially centralized, see |zz|. + • {cursorline}? (`boolean`, default: `true`) + |'cursorline'| + • {cursorlineopt}? (`string`, default: `both`) + |'cursorlineopt'| + • {debounce_delay}? (`integer`, default: `15`) Idle + milliseconds before some reload / + refresh operations. Increase if you + experience performance issues around + screen refresh. + • {side}? (`"left"|"right"`) (default: `"left"`) + • {preserve_window_proportions}? (`boolean`, default: `false`) + Preserves window proportions when + opening a file. If `false`, the height + and width of windows other than + nvim-tree will be equalized. + • {number}? (`boolean`, default: `false`) + |'number'| + • {relativenumber}? (`boolean`, default: `false`) + |'relativenumber'| + • {signcolumn}? (`"yes"|"auto"|"no"`, default: + `"yes"`) |'signcolumn'| + • {width}? (`nvim_tree.config.view.width.spec|nvim_tree.config.view.width`) + (default: `30`) + • {float}? (`nvim_tree.config.view.float`) + |nvim_tree.config.view.float| - Return: ~ - (table) as per |nvim_buf_get_keymap()| +*nvim_tree.config.view.float* + Configure floating window behaviour -============================================================================== -API: Commands *nvim-tree-api.commands* + {open_win_config} is passed to |nvim_open_win()|, default: >lua + { + relative = "editor", + border = "rounded", + width = 30, + height = 30, + row = 1, + col = 1, + } +< -commands.get() *nvim-tree-api.commands.get()* - Retrieve all commands, see |nvim-tree-commands| + Fields: ~ + • {enable}? (`boolean`) (default: `false`) + • {quit_on_focus_loss}? (`boolean`, default: `true`) Close the floating + window when it loses focus. + • {open_win_config}? (`vim.api.keyset.win_config|(fun(): vim.api.keyset.win_config)`) + (default: + `{ relative = "editor", border = "rounded", width = 30, height = 30, row = 1, col = 1, }`) - Return: ~ - (table) array containing |nvim_create_user_command()| parameters: - • {name} (string) - • {command} (function) - • {opts} (table) +*nvim_tree.config.view.width* + Configure dynamic width based on longest line. -============================================================================== -API: Diagnostics *nvim-tree-api.diagnostics* + Fields: ~ + • {min}? (`nvim_tree.config.view.width.spec`) (default: + `30`) + • {max}? (`nvim_tree.config.view.width.spec`, default: `-1`) + -1 for unbounded. + • {lines_excluded}? (`("root")[]`, default: `{ "root" }`) Exclude these + lines when computing width. + • {padding}? (`nvim_tree.config.view.width.spec`, default: `1`) + Extra padding to the right. -diagnostics.hi_test() *nvim-tree-api.diagnostics.hi_test()* - Open a new buffer displaying all nvim-tree highlight groups, their link - chain and concrete definition. - Similar to `:so $VIMRUNTIME/syntax/hitest.vim` as per |:highlight| ============================================================================== -Mappings *nvim-tree-mappings* - -Mappings are set via the |nvim_tree.config| {on_attach} function, which is run upon -creating the nvim-tree buffer. Mappings are usually |nvim-tree-api| functions -however may be your own. - -When {on_attach} is not a function, |nvim-tree-mappings-default| will be used. +Config: renderer *nvim-tree-config-renderer* -Active mappings may be viewed via HELP, default `g?`. The mapping's description -is used when displaying HELP. +*nvim_tree.config.renderer* + Controls the appearance of the tree. -The `on_attach` function is passed the `bufnr` of nvim-tree. Use -|vim.keymap.set()| or |nvim_set_keymap()| to define mappings as usual. e.g. >lua + See |nvim-tree-icons-highlighting| for {highlight_} and {decorators} + fields. - local function my_on_attach(bufnr) - local api = require("nvim-tree.api") + {root_folder_label} has 3 forms: + • `string`: |filename-modifiers| format string, default `":~:s?$?/..?"` + • `boolean`: `true` to disable + • `fun(root_cwd: string): string`: return a literal string from root's + absolute path e.g. >lua + my_root_folder_label = function(path) + return ".../" .. vim.fn.fnamemodify(path, ":t") + end +< - local function opts(desc) - return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true } - end - - -- copy default mappings here from defaults in next section - vim.keymap.set("n", "", api.tree.change_root_to_node, opts("CD")) - vim.keymap.set("n", "", api.node.open.replace_tree_buffer, opts("Open: In Place")) - --- - -- OR use all default mappings - api.config.mappings.default_on_attach(bufnr) - - -- remove a default - vim.keymap.del("n", "", { buffer = bufnr }) - - -- override a default - vim.keymap.set("n", "", api.tree.reload, opts("Refresh")) - - -- add your mappings - vim.keymap.set("n", "?", api.tree.toggle_help, opts("Help")) - --- - end + Fields: ~ + • {add_trailing}? (`boolean`, default: `false`) Appends a + trailing slash to folder and symlink folder + target names. + • {group_empty}? (`boolean|(fun(relative_path: string): string)`, default: `false`) + Compact folders that only contain a single + folder into one node. Function variant + takes the relative path of grouped folders + and returns a string to be displayed. + • {full_name}? (`boolean`, default: `false`) Display nodes + whose name length is wider than the width + of nvim-tree window in floating window. + • {root_folder_label}? (`string|boolean|(fun(root_cwd: string): string)`) + (default: `":~:s?$?/..?"`) + • {indent_width}? (`integer`, default: `2`) Number of spaces + for each tree nesting level. Minimum 1. + • {hidden_display}? (`nvim_tree.config.renderer.hidden_display`, default: `none`) + |nvim-tree-hidden-display| + • {symlink_destination}? (`boolean`, default: `true`) Appends an + arrow followed by the target of the + symlink. + • {decorators}? (`(string|nvim_tree.api.decorator.UserDecorator)[]`) + (default: + `{ "Git", "Open", "Hidden", "Modified", "Bookmark", "Diagnostics", "Copied", "Cut", }`) + • {highlight_git}? (`nvim_tree.config.renderer.highlight`) + (default: `"none"`) + • {highlight_opened_files}? (`nvim_tree.config.renderer.highlight`) + (default: `"none"`) + • {highlight_hidden}? (`nvim_tree.config.renderer.highlight`) + (default: `"none"`) + • {highlight_modified}? (`nvim_tree.config.renderer.highlight`) + (default: `"none"`) + • {highlight_bookmarks}? (`nvim_tree.config.renderer.highlight`) + (default: `"none"`) + • {highlight_diagnostics}? (`nvim_tree.config.renderer.highlight`) + (default: `"none"`) + • {highlight_clipboard}? (`nvim_tree.config.renderer.highlight`) + (default: `"name"`) + • {special_files}? (`string[]`, default: `{ "Cargo.toml", "Makefile", "README.md", "readme.md", }`) + Highlight special files and directories + with `NvimTreeSpecial*`. + • {indent_markers}? (`nvim_tree.config.renderer.indent_markers`) + |nvim_tree.config.renderer.indent_markers| + • {icons}? (`nvim_tree.config.renderer.icons`) + |nvim_tree.config.renderer.icons| - require("nvim-tree").setup({ - --- - on_attach = my_on_attach, - --- - }) -< -Single left mouse mappings can be achieved via ``. +*nvim_tree.config.renderer.icons* + Icons and separators -Single right / middle mouse mappings will require changes to |'mousemodel'| or |'mouse'|. + See |nvim-tree-icons-highlighting| for: {_placement} fields. -|vim.keymap.set()| {rhs} is a `(function|string)` thus it may be necessary to -define your own function to map complex functionality e.g. >lua + Fields: ~ + • {git_placement}? (`nvim_tree.config.renderer.icons.placement`) + (default: `before`) + • {hidden_placement}? (`nvim_tree.config.renderer.icons.placement`) + (default: `after`) + • {modified_placement}? (`nvim_tree.config.renderer.icons.placement`) + (default: `after`) + • {bookmarks_placement}? (`nvim_tree.config.renderer.icons.placement`) + (default: `signcolumn`) + • {diagnostics_placement}? (`nvim_tree.config.renderer.icons.placement`) + (default: `signcolumn`) + • {padding}? (`table`) + *nvim_tree.config.renderer.icons.padding* + • {icon}? (`string`, default: `" "`) Between + icon and filename. + • {folder_arrow}? (`string`, default: `" "`) + Between folder arrow icon and file/folder + icon. + • {symlink_arrow}? (`string`, default: `" ➛ "`) Separator + between symlink source and target. + • {show}? (`nvim_tree.config.renderer.icons.show`) + |nvim_tree.config.renderer.icons.show| + • {glyphs}? (`nvim_tree.config.renderer.icons.glyphs`) + |nvim_tree.config.renderer.icons.glyphs| + • {web_devicons}? (`nvim_tree.config.renderer.icons.web_devicons`) + |nvim_tree.config.renderer.icons.web_devicons| - local function print_node_path() - local api = require("nvim-tree.api") - local node = api.tree.get_node_under_cursor() - print(node.absolute_path) - end +*nvim_tree.config.renderer.icons.glyphs* + See |nvim-tree-icons-highlighting|. - -- on_attach - vim.keymap.set("n", "", print_node_path, opts("Print Path")) -< -============================================================================== -Mappings: Default *nvim-tree-mappings-default* + Glyphs that appear in the sign column must have length <= 2 -In the absence of an |nvim_tree.config| {on_attach} function, the following -defaults will be applied. + Fields: ~ + • {default}? (`string`, default: `""`) Files + • {symlink}? (`string`) (default: `""`) + • {bookmark}? (`string`) (default: `"󰆤"`) + • {modified}? (`string`) (default: `"●"`) + • {hidden}? (`string`) (default: `"󰜌"`) + • {folder}? (`table`) *nvim_tree.config.renderer.icons.glyphs.folder* + • {arrow_closed}? (`string`) (default: left arrow) + • {arrow_open}? (`string`) (default: down arrow) + • {default}? (`string`) (default: `""`) + • {open}? (`string`) (default: `""`) + • {empty}? (`string`) (default: `""`) + • {empty_open}? (`string`) (default: `""`) + • {symlink}? (`string`) (default: `""`) + • {symlink_open}? (`string`) (default: `""`) + • {git}? (`table`) *nvim_tree.config.renderer.icons.glyphs.git* + • {unstaged}? (`string`) (default: `"✗"`) + • {staged}? (`string`) (default: `"✓"`) + • {unmerged}? (`string`) (default: `""`) + • {renamed}? (`string`) (default: `"➜"`) + • {untracked}? (`string`) (default: `"★"`) + • {deleted}? (`string`) (default: `""`) + • {ignored}? (`string`) (default: `"◌"`) -You are encouraged to copy these to your {on_attach} function. >lua +*nvim_tree.config.renderer.icons.show* + See |nvim-tree-icons-highlighting|. - local api = require("nvim-tree.api") + Fields: ~ + • {file}? (`boolean`) (default: `true`) + • {folder}? (`boolean`) (default: `true`) + • {git}? (`boolean`) (default: `true`) + • {modified}? (`boolean`) (default: `true`) + • {hidden}? (`boolean`) (default: `false`) + • {diagnostics}? (`boolean`) (default: `true`) + • {bookmarks}? (`boolean`) (default: `true`) + • {folder_arrow}? (`boolean`, default: `true`) Show a small arrow + before the folder node. Arrow will be a part of the + node when using + |nvim_tree.config.renderer.indent_markers|. - local function opts(desc) - return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true } - end +*nvim_tree.config.renderer.icons.web_devicons* + Configure optional plugin `nvim-tree/nvim-web-devicons`, see + |nvim-tree-icons-highlighting|. - -- BEGIN_DEFAULT_ON_ATTACH - vim.keymap.set("n", "", api.tree.change_root_to_node, opts("CD")) - vim.keymap.set("n", "", api.node.open.replace_tree_buffer, opts("Open: In Place")) - vim.keymap.set("n", "", api.node.show_info_popup, opts("Info")) - vim.keymap.set("n", "", api.fs.rename_sub, opts("Rename: Omit Filename")) - vim.keymap.set("n", "", api.node.open.tab, opts("Open: New Tab")) - vim.keymap.set("n", "", api.node.open.vertical, opts("Open: Vertical Split")) - vim.keymap.set("n", "", api.node.open.horizontal, opts("Open: Horizontal Split")) - vim.keymap.set("n", "", api.node.navigate.parent_close, opts("Close Directory")) - vim.keymap.set("n", "", api.node.open.edit, opts("Open")) - vim.keymap.set("n", "", api.fs.remove, opts("Delete")) - vim.keymap.set("n", "", api.node.open.preview, opts("Open Preview")) - vim.keymap.set("n", ">", api.node.navigate.sibling.next, opts("Next Sibling")) - vim.keymap.set("n", "<", api.node.navigate.sibling.prev, opts("Previous Sibling")) - vim.keymap.set("n", ".", api.node.run.cmd, opts("Run Command")) - vim.keymap.set("n", "-", api.tree.change_root_to_parent, opts("Up")) - vim.keymap.set("n", "a", api.fs.create, opts("Create File Or Directory")) - vim.keymap.set("n", "bd", api.marks.bulk.delete, opts("Delete Bookmarked")) - vim.keymap.set("n", "bt", api.marks.bulk.trash, opts("Trash Bookmarked")) - vim.keymap.set("n", "bmv", api.marks.bulk.move, opts("Move Bookmarked")) - vim.keymap.set("n", "B", api.tree.toggle_no_buffer_filter, opts("Toggle Filter: No Buffer")) - vim.keymap.set("n", "c", api.fs.copy.node, opts("Copy")) - vim.keymap.set("n", "C", api.tree.toggle_git_clean_filter, opts("Toggle Filter: Git Clean")) - vim.keymap.set("n", "[c", api.node.navigate.git.prev, opts("Prev Git")) - vim.keymap.set("n", "]c", api.node.navigate.git.next, opts("Next Git")) - vim.keymap.set("n", "d", api.fs.remove, opts("Delete")) - vim.keymap.set("n", "D", api.fs.trash, opts("Trash")) - vim.keymap.set("n", "E", api.tree.expand_all, opts("Expand All")) - vim.keymap.set("n", "e", api.fs.rename_basename, opts("Rename: Basename")) - vim.keymap.set("n", "]e", api.node.navigate.diagnostics.next, opts("Next Diagnostic")) - vim.keymap.set("n", "[e", api.node.navigate.diagnostics.prev, opts("Prev Diagnostic")) - vim.keymap.set("n", "F", api.live_filter.clear, opts("Live Filter: Clear")) - vim.keymap.set("n", "f", api.live_filter.start, opts("Live Filter: Start")) - vim.keymap.set("n", "g?", api.tree.toggle_help, opts("Help")) - vim.keymap.set("n", "gy", api.fs.copy.absolute_path, opts("Copy Absolute Path")) - vim.keymap.set("n", "ge", api.fs.copy.basename, opts("Copy Basename")) - vim.keymap.set("n", "H", api.tree.toggle_hidden_filter, opts("Toggle Filter: Dotfiles")) - vim.keymap.set("n", "I", api.tree.toggle_gitignore_filter, opts("Toggle Filter: Git Ignore")) - vim.keymap.set("n", "J", api.node.navigate.sibling.last, opts("Last Sibling")) - vim.keymap.set("n", "K", api.node.navigate.sibling.first, opts("First Sibling")) - vim.keymap.set("n", "L", api.node.open.toggle_group_empty, opts("Toggle Group Empty")) - vim.keymap.set("n", "M", api.tree.toggle_no_bookmark_filter, opts("Toggle Filter: No Bookmark")) - vim.keymap.set("n", "m", api.marks.toggle, opts("Toggle Bookmark")) - vim.keymap.set("n", "o", api.node.open.edit, opts("Open")) - vim.keymap.set("n", "O", api.node.open.no_window_picker, opts("Open: No Window Picker")) - vim.keymap.set("n", "p", api.fs.paste, opts("Paste")) - vim.keymap.set("n", "P", api.node.navigate.parent, opts("Parent Directory")) - vim.keymap.set("n", "q", api.tree.close, opts("Close")) - vim.keymap.set("n", "r", api.fs.rename, opts("Rename")) - vim.keymap.set("n", "R", api.tree.reload, opts("Refresh")) - vim.keymap.set("n", "s", api.node.run.system, opts("Run System")) - vim.keymap.set("n", "S", api.tree.search_node, opts("Search")) - vim.keymap.set("n", "u", api.fs.rename_full, opts("Rename: Full Path")) - vim.keymap.set("n", "U", api.tree.toggle_custom_filter, opts("Toggle Filter: Hidden")) - vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse All")) - vim.keymap.set("n", "x", api.fs.cut, opts("Cut")) - vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name")) - vim.keymap.set("n", "Y", api.fs.copy.relative_path, opts("Copy Relative Path")) - vim.keymap.set("n", "<2-LeftMouse>", api.node.open.edit, opts("Open")) - vim.keymap.set("n", "<2-RightMouse>", api.tree.change_root_to_node, opts("CD")) - -- END_DEFAULT_ON_ATTACH -< -Alternatively, you may apply these default mappings from your |nvim_tree.config| {on_attach} via -|nvim-tree-api.config.mappings.default_on_attach()| e.g. >lua + Fields: ~ + • {file}? (`table`) + *nvim_tree.config.renderer.icons.web_devicons.file* + • {enable}? (`boolean`) (default: `true`) + • {color}? (`boolean`) (default: `true`) + • {folder}? (`table`) + *nvim_tree.config.renderer.icons.web_devicons.folder* + • {enable}? (`boolean`) (default: `false`) + • {color}? (`boolean`) (default: `true`) - local function my_on_attach(bufnr) - local api = require("nvim-tree.api") +*nvim_tree.config.renderer.indent_markers* - local function opts(desc) - return { desc = "nvim-tree: " .. desc, buffer = bufnr, noremap = true, silent = true, nowait = true } - end + Fields: ~ + • {enable}? (`boolean`, default: `false`) Display indent markers + when folders are open. + • {inline_arrows}? (`boolean`, default: `true`) Display folder arrows + in the same column as indent marker when using + |nvim_tree.config.renderer.icons.padding| + {folder_arrow} + • {icons}? (`table`) + *nvim_tree.config.renderer.indent_markers.icons* + Before the file/directory, length 1. + • {corner}? (`string`) (default: `"└"`) + • {edge}? (`string`) (default: `"│"`) + • {item}? (`string`) (default: `"│"`) + • {bottom}? (`string`) (default: `"─"`) + • {none}? (`string`) (default: `" "`) - api.config.mappings.default_on_attach(bufnr) - -- your removals and mappings go here - end -< ============================================================================== -Icons And Highlighting *nvim-tree-icons-highlighting* +Config: hijack_directories *nvim-tree-config-hijack-directories* -Icons may be displayed before files and directories. +*nvim_tree.config.hijack_directories* + Hijack directory buffers by replacing the directory buffer with the tree. -Additional icons and highlighting may be displayed to indicate various states -for files and and directories. + Disable this option if you use vim-dirvish or dirbuf.nvim. -Highlighting is additive, with higher precedence overriding lower. - -|nvim_tree.config.renderer| {decorators} controls which highlighting is -applied and its precedence. See |nvim-tree-decorators| for information on -creating custom decorators. -< -`ICON` - Enable via |nvim_tree.config.renderer.icons.show - -`REQUIRES` - Feature must be enabled to show icons and highlighting. - -`PLACEMENT` *nvim_tree.config.renderer.icons.placement* - Where to place the icon: |nvim_tree.config.renderer.icons| {_placement} - • `before`: before file/folder, after the file/folders icons - • `after`: after file/folder - • `signcolumn`: far left, requires |nvim_tree.config.view| {signcolumn}. - • `right_align`: far right - -`HIGHLIGHT` *nvim_tree.config.renderer.highlight* - What should be highlighted: |nvim_tree.config.renderer| {highlight_} - • `none`: no highlighting - • `icon`: icon only - • `name`: name only - • `all`: icon and name + If |nvim_tree.config| {hijack_netrw} and {disable_netrw} are `false` this + feature will be disabled. -`DEVICONS` - Glyphs and their colors will be overridden by optional plugin: - `nvim-tree/nvim-web-devicons` |nvim_tree.config.renderer.icons.web_devicons| + Fields: ~ + • {enable}? (`boolean`) (default: `true`) + • {auto_open}? (`boolean`, default: `true`) Open if the tree was + previously closed. -`GLYPHS` - Icon glyphs definitions. -`GROUPS` - Applicable highlight groups: |nvim-tree-highlight-groups| -Some defaults noted. In ascending order of default highlight precedence: +============================================================================== +Config: update_focused_file *nvim-tree-config-update-focused-file* -`WHAT ICON REQUIRES PLACEMENT HIGHLIGHT GLYPHS DEVICONS GROUPS` -File Icon {file} Y - - - |nvim_tree.config.renderer.icons.glyphs| {default} Y `NvimTreeNormal`, `NvimTreeFileIcon` -Folder Icon {folder} Y - - - |nvim_tree.config.renderer.icons.glyphs.folder| Y `NvimTree*FolderName`, `NvimTree*FolderIcon` -Git Status {git} Y |nvim_tree.config.git| {git_placement} `"before"` {highlight_git} `"none"` |nvim_tree.config.renderer.icons.glyphs.git| N `NvimTreeGit*` -|bufloaded()| - - - {highlight_opened_files}`"none"` - N ` NvimTreeOpened*` -Dotfiles {hidden} N - {hidden_placement} `"after"` {highlight_hidden} `"none"` |nvim_tree.config.renderer.icons.glyphs| {hidden} N `NvimTreeHidden*` -|'modified'| {modified} Y |nvim_tree.config.modified| {modified_placement} `"after"` {highlight_modified} `"none"` |nvim_tree.config.renderer.icons.glyphs| {modified} N `NvimTreeModified*` -Bookmarked {bookmarks} Y - {bookmarks_placement} `"signcolumn"` {highlight_bookmarks} `"none"` |nvim_tree.config.renderer.icons.glyphs| {bookmark} N `NvimTreeBookmark*` -Diag Status {diagnostics}Y |nvim_tree.config.diagnostics| {diagnostics_placement}`"signcolumn"` {highlight_diagnostics} `"none" ` |nvim_tree.config.diagnostics.icons| N `NvimTreeDiagnostic*` -Cut/Copied - - - {highlight_clipboard} `"name"` - N `NvimTreeCutHL`, `NvimTreeCopiedHL` +*nvim_tree.config.update_focused_file* + Update the focused file on |BufEnter|, uncollapsing folders recursively. + Fields: ~ + • {enable}? (`boolean`) (default: `false`) + • {update_root}? (`nvim_tree.config.update_focused_file.update_root`) + |nvim_tree.config.update_focused_file.update_root| + • {exclude}? (`boolean|(fun(args: vim.api.keyset.create_autocmd.callback_args): boolean)`, default: `false`) + A function called on |BufEnter| that returns true if + the file should not be focused when opening. -============================================================================== -Highlight Groups *nvim-tree-highlight-groups* +*nvim_tree.config.update_focused_file.update_root* + Update the root directory of the tree if the file is not under the current + root directory. -All the following highlight groups can be configured by hand. Aside from -`NvimTreeWindowPicker`, it is not advised to colorize the background of these -groups. + Prefers vim's cwd and |nvim_tree.config| {root_dirs}, falling back to the + directory containing the file. -Example |:highlight| >vim - :hi NvimTreeSymlink guifg=blue gui=bold,underline -< -It is recommended to enable |'termguicolors'| for the more pleasant 24-bit -colours. + Requires |nvim_tree.config.update_focused_file| -To view the nvim-tree highlight groups run |:NvimTreeHiTest| + Fields: ~ + • {enable}? (`boolean`) (default: `false`) + • {ignore_list}? (`string[]`, default: `{}`) List of buffer names and + filetypes that will not update the root dir of the + tree if the file isn't found under the current root + directory. -To view all active highlight groups run `:so $VIMRUNTIME/syntax/hitest.vim` -as per |:highlight| -The `*HL` groups are additive as per |nvim_tree.config.renderer| precedence. -Only present attributes will clobber each other. -In this example a modified, opened file will have magenta text, with cyan -undercurl: >vim - :hi NvimTreeOpenedHL guifg=magenta guisp=red gui=underline - :hi NvimTreeModifiedFileHL guisp=cyan gui=undercurl -< -To prevent usage of a highlight: -- Before setup: link the group to `Normal` e.g. >vim - :hi NvimTreeExecFile Normal -< -- After setup: link it to `NONE`, to override the default link e.g. >lua - :hi! link NvimTreeExecFile NONE -< ============================================================================== -Highlight Groups: Default *nvim-tree-highlight-groups-default* +Config: system_open *nvim-tree-config-system-open* -|:highlight-link| `default` or |:highlight-default| define the groups on setup: +*nvim_tree.config.system_open* + Open files or directories via the OS. -Standard: > - NvimTreeNormal Normal - NvimTreeNormalFloat NormalFloat - NvimTreeNormalNC NormalFloat + Nvim: + • `>=` 0.10 uses |vim.ui.open()| unless {cmd} is specified + • `<` 0.10 calls external {cmd}: + • UNIX: `xdg-open` + • macOS: `open` + • Windows: `cmd` - NvimTreeLineNr LineNr - NvimTreeWinSeparator WinSeparator - NvimTreeEndOfBuffer EndOfBuffer - NvimTreePopup Normal - NvimTreeSignColumn NvimTreeNormal + Once nvim-tree minimum Nvim version is updated to 0.10, these options will + no longer be necessary and will be removed. - NvimTreeCursorColumn CursorColumn - NvimTreeCursorLine CursorLine - NvimTreeCursorLineNr CursorLineNr + Fields: ~ + • {cmd}? (`string`) The open command itself + • {args}? (`string[]`, default: `{}` or `{ "/c", "start", '""' }` on + windows) Optional argument list. Leave empty for OS specific + default. - NvimTreeStatusLine StatusLine - NvimTreeStatusLineNC StatusLineNC -< -File Text: > - NvimTreeExecFile SpellCap - NvimTreeImageFile SpellCap - NvimTreeSpecialFile SpellCap - NvimTreeSymlink SpellCap -< -Folder Text: > - NvimTreeRootFolder Title - NvimTreeFolderName Directory - NvimTreeEmptyFolderName Directory - NvimTreeOpenedFolderName Directory - NvimTreeSymlinkFolderName Directory -< -File Icons: > - NvimTreeFileIcon NvimTreeNormal - NvimTreeSymlinkIcon NvimTreeNormal -< -Folder Icons: > - NvimTreeFolderIcon guifg=#8094b4 ctermfg=Blue - NvimTreeOpenedFolderIcon NvimTreeFolderIcon - NvimTreeClosedFolderIcon NvimTreeFolderIcon - NvimTreeFolderArrowClosed NvimTreeIndentMarker - NvimTreeFolderArrowOpen NvimTreeIndentMarker -< -Indent: > - NvimTreeIndentMarker NvimTreeFileIcon -< -Picker: > - NvimTreeWindowPicker guifg=#ededed guibg=#4493c8 gui=bold ctermfg=White ctermbg=Cyan -< -Live Filter: > - NvimTreeLiveFilterPrefix PreProc - NvimTreeLiveFilterValue ModeMsg -< -Clipboard: > - NvimTreeCopiedHL SpellRare - NvimTreeCutHL SpellBad -< -Bookmarks: > - NvimTreeBookmarkIcon NvimTreeFolderIcon - NvimTreeBookmarkHL SpellLocal -< -Modified: > - NvimTreeModifiedIcon Type - NvimTreeModifiedFileHL NvimTreeModifiedIcon - NvimTreeModifiedFolderHL NvimTreeModifiedIcon -Hidden: > - NvimTreeModifiedIcon Conceal - NvimTreeModifiedFileHL NvimTreeHiddenIcon - NvimTreeModifiedFolderHL NvimTreeHiddenFileHL -< -Hidden Display: > - NvimTreeHiddenDisplay Conceal -< -Opened: > - NvimTreeOpenedHL Special -< -Git Icon: > - NvimTreeGitDeletedIcon Statement - NvimTreeGitDirtyIcon Statement - NvimTreeGitIgnoredIcon Comment - NvimTreeGitMergeIcon Constant - NvimTreeGitNewIcon PreProc - NvimTreeGitRenamedIcon PreProc - NvimTreeGitStagedIcon Constant -< -Git File File Highlight: > - NvimTreeGitFileDeletedHL NvimTreeGitDeletedIcon - NvimTreeGitFileDirtyHL NvimTreeGitDirtyIcon - NvimTreeGitFileIgnoredHL NvimTreeGitIgnoredIcon - NvimTreeGitFileMergeHL NvimTreeGitMergeIcon - NvimTreeGitFileNewHL NvimTreeGitNewIcon - NvimTreeGitFileRenamedHL NvimTreeGitRenamedIcon - NvimTreeGitFileStagedHL NvimTreeGitStagedIcon -< -Git Folder Folder Highlight: > - NvimTreeGitFolderDeletedHL NvimTreeGitFileDeletedHL - NvimTreeGitFolderDirtyHL NvimTreeGitFileDirtyHL - NvimTreeGitFolderIgnoredHL NvimTreeGitFileIgnoredHL - NvimTreeGitFolderMergeHL NvimTreeGitFileMergeHL - NvimTreeGitFolderNewHL NvimTreeGitFileNewHL - NvimTreeGitFolderRenamedHL NvimTreeGitFileRenamedHL - NvimTreeGitFolderStagedHL NvimTreeGitFileStagedHL -< -Diagnostics Icon: > - NvimTreeDiagnosticErrorIcon DiagnosticError - NvimTreeDiagnosticWarnIcon DiagnosticWarn - NvimTreeDiagnosticInfoIcon DiagnosticInfo - NvimTreeDiagnosticHintIcon DiagnosticHint -< -Diagnostics File Highlight: > - NvimTreeDiagnosticErrorFileHL DiagnosticUnderlineError - NvimTreeDiagnosticWarnFileHL DiagnosticUnderlineWarn - NvimTreeDiagnosticInfoFileHL DiagnosticUnderlineInfo - NvimTreeDiagnosticHintFileHL DiagnosticUnderlineHint -< -Diagnostics Folder Highlight: > - NvimTreeDiagnosticErrorFolderHL NvimTreeDiagnosticErrorFileHL - NvimTreeDiagnosticWarnFolderHL NvimTreeDiagnosticWarnFileHL - NvimTreeDiagnosticInfoFolderHL NvimTreeDiagnosticInfoFileHL - NvimTreeDiagnosticHintFolderHL NvimTreeDiagnosticHintFileHL -< -============================================================================== -Events *nvim-tree-events* -nvim-tree will dispatch events whenever an action is made. These events can be -subscribed to through handler functions. This allows for even further -customization of nvim-tree. +============================================================================== +Config: git *nvim-tree-config-git* -A handler for an event is just a function which receives one argument, the -payload of the event. The payload is different for each event type. Refer -to |nvim_tree_registering_handlers| for more information. +*nvim_tree.config.git* + Git operations are run in the background thus status may not immediately + appear. -*nvim_tree_registering_handlers* + Processes will be killed if they exceed {timeout} ms. Git integration will + be disabled following 5 timeouts and you will be notified. -Handlers are registered by calling |nvim-tree-api.events.subscribe()| -function with an |nvim-tree-api.events.Event| + Git integration may be disabled for git top-level directories via + {disable_for_dirs}: + • A list of relative paths evaluated with |fnamemodify()| `:p` OR + • A function that is passed an absolute path and returns `true` to disable -e.g. handler for node renamed: >lua + See |nvim-tree-icons-highlighting|. - local api = require("nvim-tree.api") - local Event = api.events.Event + Fields: ~ + • {enable}? (`boolean`) (default: `true`) + • {show_on_dirs}? (`boolean`, default: `true`) Show status icons + of children when directory itself has no status + icon + • {show_on_open_dirs}? (`boolean`, default: `true`) Show status icons + of children on directories that are open. + Requires {show_on_dirs}. + • {disable_for_dirs}? (`string[]|(fun(path: string): boolean)`, + default: `{}`) Disable for top level paths. + • {timeout}? (`integer`, default: `400`) `git` processes + timeout milliseconds. + • {cygwin_support}? (`boolean`, default: `false`) Use `cygpath` if + available to resolve paths for git. - api.events.subscribe(Event.NodeRenamed, function(data) - print("Node renamed from " .. data.old_name .. " to " .. data.new_name) - end) -< -*nvim_tree_events_kind* -- Event.Ready - When NvimTree has been initialized. - • Note: Handler takes no parameter. -- Event.TreePreOpen - Invoked before the window and buffer for NvimTree are created - or opened. Before `Event.TreeOpen` - • Note: Handler takes no parameter. +============================================================================== +Config: diagnostics *nvim-tree-config-diagnostics* -- Event.TreeOpen - Invoked after the NvimTree is opened. - • Note: Handler takes no parameter. +*nvim_tree.config.diagnostics* + Integrate with |lsp| or COC diagnostics. -- Event.TreeClose - Invoked after the NvimTree is closed, but before the window is - closed. Dispatched on |WinClosed| event for NvimTree window. - • Note: Handler takes no parameter. + See |nvim-tree-icons-highlighting|. -- Event.Resize - When NvimTree is resized. - handler parameters: ~ - size: `number` size of the view in columns. + Fields: ~ + • {enable}? (`boolean`) (default: `false`) + • {debounce_delay}? (`integer`, default: `500`) Idle milliseconds + between diagnostic event and tree update. + • {show_on_dirs}? (`boolean`, default: `false`) Show diagnostic + icons on parent directories. + • {show_on_open_dirs}? (`boolean`, default: `true`) Show diagnostics + icons on directories that are open. Requires + {show_on_dirs}. + • {diagnostic_opts}? (`boolean`, default: `false`) Global + |vim.diagnostic.Opts| overrides {severity} and + {icons} + • {severity}? (`table`) + *nvim_tree.config.diagnostics.severity* + • {min}? (`vim.diagnostic.Severity`, default: + HINT) |vim.diagnostic.severity| + • {max}? (`vim.diagnostic.Severity`, default: + ERROR) |vim.diagnostic.severity| + • {icons}? (`table`) *nvim_tree.config.diagnostics.icons* + • {hint}? (`string`) (default: `""` ) + • {info}? (`string`) (default: `""` ) + • {warning}? (`string`) (default: `""` ) + • {error}? (`string`) (default: `""` ) -- Event.WillRenameNode - • Note: A node can either be a file or a directory. - handler parameters: ~ - {old_name} `{string}` Absolute path to the old node location. - {new_name} `{string}` Absolute path to the new node location. -- Event.NodeRenamed - • Note: A node can either be a file or a directory. - handler parameters: ~ - {old_name} `{string}` Absolute path to the old node location. - {new_name} `{string}` Absolute path to the new node location. -- Event.FileCreated - handler parameters: ~ - {fname} `{string}` Absolute path to the created file +============================================================================== +Config: modified *nvim-tree-config-modified* -- Event.WillCreateFile - handler parameters: ~ - {fname} `{string}` Absolute path to the file to be - created +*nvim_tree.config.modified* + Indicate which files have unsaved modification. To see modified status in + the tree you will need: + • |nvim_tree.config.renderer.icons.show| {modified} OR + • |nvim_tree.config.renderer| {highlight_modified} -- Event.FileRemoved - handler parameters: ~ - {fname} `{string}` Absolute path to the removed file. + See |nvim-tree-icons-highlighting|. -- Event.WillRemoveFile - handler parameters: ~ - {fname} `{string}` Absolute path to the file to be - removed + Fields: ~ + • {enable}? (`boolean`) (default: `false`) + • {show_on_dirs}? (`boolean`, default: `true`) Show modified + indication on directory whose children are + modified. + • {show_on_open_dirs}? (`boolean`, default: `false`) Show modified + indication on open directories. Requires + {show_on_dirs}. -- Event.FolderCreated - handler parameters: ~ - {folder_name} `{string}` Absolute path to the created folder. -- Event.FolderRemoved - handler parameters: ~ - {folder_name} `{string}` Absolute path to the removed folder. -- Event.TreeAttachedPost - Invoked after the tree's buffer has been created and mappings - have been applied: |nvim-tree-mappings| or |nvim_tree.config| {on_attach} - handler parameters: ~ - {buf} `{number} `API buffer handle (buffer number) +============================================================================== +Config: filters *nvim-tree-config-filters* -- Event.TreeRendered - Invoked every time the tree is redrawn. Normally this event - happens after `Event.TreeOpen` except that handlers of this - one will have access to the tree buffer populated with the - final content. - handler parameters: ~ - {bufnr} `{number} `API buffer handle (buffer number) - {winnr} `{number} `API window handle (window number) +*nvim_tree.config.filters* + Filters may be applied to the tree to exlude the display of + file/directories. -*nvim_tree_events_startup* + Multiple filters may be applied at once. -There are two special startup events in the form of User autocommands: + Filters can be set at startup or toggled live via API with default + mappings. -`NvimTreeRequired` first `require("nvim-tree")` -`NvimTreeSetup` `setup({})` completed + `I `{git_ignored}` `|nvim_tree.api.filter.git.ignored.toggle()| + Ignore files based on `.gitignore`. Requires |nvim_tree.config.git| -Immediately before firing: a global variable of the same name will be set to a -value of 1. + `H `{dotfiles}` `|nvim_tree.api.filter.dotfiles.toggle()| + Filter dotfiles: files/directories starting with a `.` -Example subscription: >lua + `C `{git_clean}` `|nvim_tree.api.filter.git.clean.toggle()| + Filter files with no git status. `.gitignore` files will not be filtered + when {git_ignored}, as they are effectively dirty. - vim.api.nvim_create_autocmd("User", { - pattern = "NvimTreeRequired", - callback = function(data) - --- - end, - }) -< -============================================================================== -Prompts *nvim-tree-prompts* + `B `{no_buffer}` `|nvim_tree.api.filter.no_buffer.toggle()| + Filter files that have no |buflisted()| buffer. For performance reasons + buffer delete/wipe may not be immediately shown. A reload or filesystem + event will always result in an update. -Some NvimTree actions use the builtin |vim.ui.select()| prompt API for -confirmations when the |nvim_tree.config| {select_prompts} option is set. + `M `{no_bookmark}` `|nvim_tree.api.filter.no_bookmark.toggle()| + Filter files that are not bookmarked. Enabling this is not useful as there + is no means yet to persist bookmarks. -The API accepts the optional `kind` key as part of the {opts} parameter, which -can can be used to identify the type of prompt, to allow user side -configurations for different types of prompts. + `U `{custom}` `|nvim_tree.api.filter.custom.toggle()| + Disable specific file/directory names via: + • a list of backslash escaped |vim.regex| strings e.g. `"^\\.git""` + • a function passed the absolute path of the directory. -- `nvimtree_overwrite_rename` - overwrite or rename during |nvim-tree-api.fs.paste()| + All filters including live filter may be disabled via {enable} and toggled + with |nvim_tree.api.filter.toggle()| -- `nvimtree_remove` - delete during |nvim-tree-api.fs.remove()| + Files/directories may be {exclude}d from filtering: they will always be + shown, overriding {git_ignored}, {dotfiles} and {custom}. -- `nvimtree_trash` - send to trash during |nvim-tree-api.fs.trash()| + Fields: ~ + • {enable}? (`boolean`, default: `true`) Enable all filters. + • {git_ignored}? (`boolean`) (default: `true`) + • {dotfiles}? (`boolean`) (default: `false`) + • {git_clean}? (`boolean`) (default: `false`) + • {no_buffer}? (`boolean`) (default: `false`) + • {no_bookmark}? (`boolean`) (default: `false`) + • {custom}? (`string[]|(fun(absolute_path: string): boolean)`) + (default: `{}`) + • {exclude}? (`string[]`) (default: `{}`) -- `nvimtree_bulk_delete` - delete all bookmarked during |nvim-tree-api.marks.bulk.delete()| -- `nvimtree_bulk_trash` - send all bookmarked to trash during |nvim-tree-api.marks.bulk.trash()| ============================================================================== -Decorators *nvim-tree-decorators* +Config: live_filter *nvim-tree-config-live-filter* -Highlighting and icons for nodes are provided by Decorators. You may provide -your own in addition to the builtin decorators. +*nvim_tree.config.live_filter* + Live filter allows you to filter the tree nodes dynamically, based on + regex matching, see |vim.regex| -Decorators may: -- Add icons -- Set highlight group for the name or icons -- Override node icon + This feature is bound to the `f` key by default. The filter can be cleared + with the `F` key by default. + + Fields: ~ + • {prefix}? (`string`, default: `"[FILTER]: "`) Prefix of + the filter displayed in the buffer. + • {always_show_folders}? (`boolean`, default: `true`) Whether to filter + folders or not. -Create a `nvim_tree.api.decorator.UserDecorator` class and register it with -precedence via |nvim_tree.config.renderer| {decorators} -See |nvim-tree-decorator-example| ============================================================================== -Decorators: Example *nvim-tree-decorator-example* +Config: filesystem_watchers *nvim-tree-config-filesystem-watchers* -A decorator class for nodes named "example", overridind all builtin decorators -except for Cut. +*nvim_tree.config.filesystem_watchers* + Use file system watchers (libuv `uv_fs_event_t`) to monitor the filesystem + for changes and update the tree. -- Highlights node name with `IncSearch` -- Creates two icons `"1"` and `"2"` placed after the node name, highlighted with - `DiffAdd` and `DiffText` -- Replaces the node icon with `"N"`, highlighted with `Error ` + With this feature, the tree will be partially updated on specific + directory changes, resulting in better performance. -Create a class file `~/.config/nvim/lua/my-decorator.lua` + Watchers may be disabled for absolute directory paths via {ignore_dirs}. + • A list of |vim.regex| to match a path, backslash escaped e.g. + `"my-proj/\\.build$"` OR + • A function that is passed an absolute path and returns `true` to disable + This may be useful when a path is not in `.gitignore` or git integration + is disabled. -Require and register it during |nvim-tree-setup|: ->lua - local MyDecorator = require("my-decorator") + After {max_events} consecutive filesystem events on a single directory + with an interval < {debounce_delay}: + • The filesystem watcher will be disabled for that directory. + • A warning notification will be shown. + • Consider adding this directory to {ignore_dirs} - require("nvim-tree").setup({ - renderer = { - decorators = { - "Git", - "Open", - "Hidden", - "Modified", - "Bookmark", - "Diagnostics", - "Copied", - MyDecorator, - "Cut", - }, - }, - }) -< -Contents of `my-decorator.lua`: ->lua - ---@class (exact) MyDecorator: nvim_tree.api.decorator.UserDecorator - ---@field private my_icon1 nvim_tree.api.HighlightedString - ---@field private my_icon2 nvim_tree.api.HighlightedString - ---@field private my_icon_node nvim_tree.api.HighlightedString - ---@field private my_highlight_group string - local MyDecorator = require("nvim-tree.api").decorator.UserDecorator:extend() + Fields: ~ + • {enable}? (`boolean`) (default: `true`) + • {debounce_delay}? (`integer`, default: `50`) Idle milliseconds + between filesystem change and tree update. + • {ignore_dirs}? (`string[]|(fun(path: string): boolean)`, default: `{ "/.ccls-cache", "/build", "/node_modules", "/target", }`) + Disable for specific directories. + • {max_events}? (`integer`, default: `100`) Disable for a single + directory after {max_events} consecutive events + with an interval < {debounce_delay}. - ---Mandatory constructor :new() will be called once per tree render, with no arguments. - function MyDecorator:new() - self.enabled = true - self.highlight_range = "name" - self.icon_placement = "after" - -- create your icons and highlights once, applied to every node - self.my_icon1 = { str = "1", hl = { "DiffAdd" } } - self.my_icon2 = { str = "2", hl = { "DiffText" } } - self.my_icon_node = { str = "N", hl = { "Error" } } - self.my_highlight_group = "IncSearch" - -- Define the icon signs only once - -- Only needed if you are using icon_placement = "signcolumn" - -- self:define_sign(self.my_icon1) - -- self:define_sign(self.my_icon2) - end +============================================================================== +Config: actions *nvim-tree-config-actions* - ---Override node icon - ---@param node nvim_tree.api.Node - ---@return nvim_tree.api.HighlightedString? icon_node - function MyDecorator:icon_node(node) - if node.name == "example" then - return self.my_icon_node - else - return nil - end - end +*nvim_tree.config.actions* - ---Return two icons for DecoratorIconPlacement "after" - ---@param node nvim_tree.api.Node - ---@return nvim_tree.api.HighlightedString[]? icons - function MyDecorator:icons(node) - if node.name == "example" then - return { self.my_icon1, self.my_icon2, } - else - return nil - end - end + Fields: ~ + • {use_system_clipboard}? (`boolean`, default: `true`) Use the system + clipboard for copy/paste. Copied text will be + stored in registers `+` (system), otherwise, + it will be stored in `1` and `"` + • {change_dir}? (`nvim_tree.config.actions.change_dir`) + |nvim_tree.config.actions.change_dir| + • {expand_all}? (`nvim_tree.config.actions.expand_all`) + |nvim_tree.config.actions.expand_all| + • {file_popup}? (`nvim_tree.config.actions.file_popup`) + |nvim_tree.config.actions.file_popup| + • {open_file}? (`nvim_tree.config.actions.open_file`) + |nvim_tree.config.actions.open_file| + • {remove_file}? (`nvim_tree.config.actions.remove_file`) + |nvim_tree.config.actions.remove_file| - ---Exactly one highlight group for DecoratorHighlightRange "name" - ---@param node nvim_tree.api.Node - ---@return string? highlight_group - function MyDecorator:highlight_group(node) - if node.name == "example" then - return self.my_highlight_group - else - return nil - end - end +*nvim_tree.config.actions.change_dir* + vim |current-directory| behaviour - return MyDecorator -< -============================================================================== -OS Specific Restrictions *nvim-tree-os-specific* + Fields: ~ + • {enable}? (`boolean`, default: `true`) Change the working + directory when changing directories in the tree + • {global}? (`boolean`, default: `false`) Use `:cd` instead + of `:lcd` when changing directories. + • {restrict_above_cwd}? (`boolean`, default: `false`) Restrict changing + to a directory above the global cwd. -Windows WSL and PowerShell -- Trash is synchronized -- Executable file detection is disabled as this is non-performant and can - freeze Nvim -- Some filesystem watcher error related to permissions will not be reported +*nvim_tree.config.actions.expand_all* + Configure |nvim_tree.api.tree.expand_all()| and + |nvim_tree.api.node.expand()| -Powershell -- Observed Nvim hanging after a runaway (infinite) number of events on a - single directory. See |nvim_tree.config.filesystem_watchers| {max_events} + Fields: ~ + • {max_folder_discovery}? (`integer`, default: `300`) Limit the number + of folders being explored when expanding + every folder. Avoids hanging Nvim when + running this action on very large folders. + • {exclude}? (`string[]`, default: `{}`) A list of + directories that should not be expanded + automatically e.g + `{ ".git", "target", "build" }` -============================================================================== -netrw *nvim-tree-netrw* +*nvim_tree.config.actions.file_popup* + {file_popup} floating window. -|netrw| is a standard Nvim plugin that is enabled by default. It provides, -amongst other functionality, a file/directory browser. + {open_win_config} is passed to |nvim_open_win()|, default: >lua + { + col = 1, + row = 1, + relative = "cursor", + border = "shadow", + style = "minimal", + } +< -It interferes with nvim-tree and the intended user experience is nvim-tree -replacing the |netrw| browser. + You shouldn't define {width} and {height} values here. They will be + overridden to fit the file_popup content. -It is strongly recommended to disable |netrw|. As it is a bundled plugin it -must be disabled manually at the start of your `init.lua` as per |netrw-noload|: >lua + Fields: ~ + • {open_win_config}? (`vim.api.keyset.win_config`) (default: + `{ col = 1, row = 1, relative = "cursor", border = "shadow", style = "minimal", }`) - vim.g.loaded_netrw = 1 - vim.g.loaded_netrwPlugin = 1 -< -There are many |netrw| features beyond the file browser. If you want to -keep using |netrw| without its browser features please ensure: +*nvim_tree.config.actions.open_file* + Opening files. -|nvim_tree.config| {disable_netrw}` = false` -|nvim_tree.config| {hijack_netrw}` = true` + Fields: ~ + • {quit_on_open}? (`boolean`, default: `false`) Closes the explorer + when opening a file + • {eject}? (`boolean`, default: `true`) Prevent new opened file + from opening in the same window as the tree. + • {resize_window}? (`boolean`, default: `true`) Resizes the tree when + opening a file + • {window_picker}? (`nvim_tree.config.actions.open_file.window_picker`) + |nvim_tree.config.actions.open_file.window_picker| -============================================================================== -Legacy *nvim-tree-legacy* +*nvim_tree.config.actions.open_file.window_picker* + A window picker will be shown when there are multiple windows available to + open a file. It will show a single character identifier in each window's + status line. -Breaking refactors have been made however the legacy versions will be silently -migrated and used. -There are no plans to remove this migration. + When it is not enabled the file will open in the window from which you + last opened the tree, obeying {exclude} -============================================================================== -Legacy: Config *nvim-tree-legacy-opts* + You may define a {picker} function that should return the window id that + will open the node, or `nil` if an invalid window is picked or user + cancelled the action. The picker may create a new window. -Legacy config is translated to the current, making type and value changes as -needed. + Fields: ~ + • {enable}? (`boolean`) (default: `true`) + • {picker}? (`"default"|(fun(): integer)`, default: `"default"`) + Change the default window picker or define your own. + • {chars}? (`string`, default: + `"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"`) Identifier + characters to use. + • {exclude}? (`nvim_tree.config.actions.open_file.window_picker.exclude`) + |nvim_tree.config.actions.open_file.window_picker.exclude| -`update_cwd` |nvim_tree.config| {sync_root_with_cwd} -`update_focused_file.update_cwd` |nvim_tree.config.update_focused_file| {update_root} -`open_on_tab` |nvim_tree.config.tab.sync| {open} -`ignore_buf_on_tab_change` |nvim_tree.config.tab.sync| {ignore} -`renderer.root_folder_modifier` |nvim_tree.config.renderer| {root_folder_label} -`update_focused_file.debounce_delay` |nvim_tree.config.view| {debounce_delay} -`trash.require_confirm` |nvim_tree.config.ui.confirm| {trash} -`view.adaptive_size` |nvim_tree.config.view| {width} -`sort_by` |nvim_tree.config.sort| {sorter} -`git.ignore` |nvim_tree.config.filters| {git_ignored} -`renderer.icons.webdev_colors` |nvim_tree.config.renderer.icons.web_devicons.file| {color} -`renderer.icons.padding` |nvim_tree.config.renderer.icons.padding| {icon} +*nvim_tree.config.actions.open_file.window_picker.exclude* + Tables of buffer option names mapped to a list of option values. Windows + containing matching buffers will not be: + • available when using a window picker + • selected when not using a window picker -============================================================================== -Legacy: Highlight *nvim-tree-legacy-highlight* + Fields: ~ + • {filetype}? (`string[]`) (default: + `{ "notify", "lazy", "qf", "diff", "fugitive", "fugitiveblame", }`) + • {buftype}? (`string[]`) (default: + `{ "nofile", "terminal", "help", }`) -Legacy highlight group are still obeyed when they are defined and the current -highlight group is not, hard linking as follows: > +*nvim_tree.config.actions.remove_file* + Removing files. - NvimTreeModifiedIcon NvimTreeModifiedFile - NvimTreeOpenedHL NvimTreeOpenedFile - NvimTreeBookmarkIcon NvimTreeBookmark + Fields: ~ + • {close_window}? (`boolean`, default: `true`) Close any window that + displays a file when removing that file from the + tree. - NvimTreeGitDeletedIcon NvimTreeGitDeleted - NvimTreeGitDirtyIcon NvimTreeGitDirty - NvimTreeGitIgnoredIcon NvimTreeGitIgnored - NvimTreeGitMergeIcon NvimTreeGitMerge - NvimTreeGitNewIcon NvimTreeGitNew - NvimTreeGitRenamedIcon NvimTreeGitRenamed - NvimTreeGitStagedIcon NvimTreeGitStaged - NvimTreeGitFileDeletedHL NvimTreeFileDeleted - NvimTreeGitFileDirtyHL NvimTreeFileDirty - NvimTreeGitFileIgnoredHL NvimTreeFileIgnored - NvimTreeGitFileMergeHL NvimTreeFileMerge - NvimTreeGitFileNewHL NvimTreeFileNew - NvimTreeGitFileRenamedHL NvimTreeFileRenamed - NvimTreeGitFileStagedHL NvimTreeFileStaged - NvimTreeGitFolderDeletedHL NvimTreeFolderDeleted - NvimTreeGitFolderDirtyHL NvimTreeFolderDirty - NvimTreeGitFolderIgnoredHL NvimTreeFolderIgnored - NvimTreeGitFolderMergeHL NvimTreeFolderMerge - NvimTreeGitFolderNewHL NvimTreeFolderNew - NvimTreeGitFolderRenamedHL NvimTreeFolderRenamed - NvimTreeGitFolderStagedHL NvimTreeFolderStaged +============================================================================== +Config: trash *nvim-tree-config-trash* - NvimTreeLspDiagnosticsError NvimTreeDiagnosticErrorIcon - NvimTreeLspDiagnosticsWarning NvimTreeDiagnosticWarnIcon - NvimTreeLspDiagnosticsInformation NvimTreeDiagnosticInfoIcon - NvimTreeLspDiagnosticsHint NvimTreeDiagnosticHintIcon +*nvim_tree.config.trash* + Files may be trashed via an external command that must be installed on + your system. + • linux: `gio trash`, from linux package `glib2` + • macOS: `trash`, from homebrew package `trash` + • windows: `trash`, requires `trash-cli` or similar + + Fields: ~ + • {cmd}? (`string`) (default: `"gio trash"` or `"trash"`) - NvimTreeLspDiagnosticsErrorText NvimTreeDiagnosticErrorFileHL - NvimTreeLspDiagnosticsWarningText NvimTreeDiagnosticWarnFileHL - NvimTreeLspDiagnosticsInformationText NvimTreeDiagnosticInfoFileHL - NvimTreeLspDiagnosticsHintText NvimTreeDiagnosticHintFileHL - NvimTreeLspDiagnosticsErrorFolderText NvimTreeDiagnosticErrorFolderHL - NvimTreeLspDiagnosticsWarningFolderText NvimTreeDiagnosticWarnFolderHL - NvimTreeLspDiagnosticsInformationFolderText NvimTreeDiagnosticInfoFolderHL - NvimTreeLspDiagnosticsHintFolderText NvimTreeDiagnosticHintFolderHL -< ============================================================================== -Hidden Display *nvim-tree-hidden-display* +Config: tab *nvim-tree-config-tab* -Show a summary of hidden files below the tree highlighted with `NvimTreeHiddenDisplay +*nvim_tree.config.tab* -Configure via |nvim_tree.config.renderer| {hidden_display} + Fields: ~ + • {sync}? (`nvim_tree.config.tab.sync`) |nvim_tree.config.tab.sync| - *nvim_tree.config.renderer.hidden_display* - • `none`: disabled - • `simple`: show how many hidden files are in a folder - • `all`: show how many hidden and the number of hidden files by reason - • `fun(hidden_stats: table): string`: returns a summary of hidden stats +*nvim_tree.config.tab.sync* -Example `"all"`: -If a folder has 14 hidden items for various reasons, the display might show: > - (14 total git: 5, dotfile: 9) -< -If a function is provided, it receives a table `hidden_stats` where keys are -reasons and values are the count of hidden files for that reason. + Fields: ~ + • {open}? (`boolean`, default: `false`) Opens the tree automatically + when switching tabpage or opening a new tabpage if the tree + was previously open. + • {close}? (`boolean`, default: `false`) Closes the tree across all + tabpages when the tree is closed. + • {ignore}? (`string[]`, default: `{}`) List of filetypes or buffer + names on new tab that will prevent `open` and `close` -The `hidden_stats` argument is structured as follows, where is the number -of hidden files related to the field: > - hidden_stats = { - bookmark = , - buf = , - custom = , - dotfile = , - git = , - live_filter = , - } -< -Example of function that can be passed: >lua - function(hidden_stats) - local total_count = 0 - for reason, count in pairs(hidden_stats) do - total_count = total_count + count - end - if total_count > 0 then - return "(" .. tostring(total_count) .. " hidden)" - end - return nil - end -< ============================================================================== -Config *nvim-tree-config* +Config: notify *nvim-tree-config-notify* -*nvim_tree.config* - Arguments to pass to |nvim-tree-setup|. +*nvim_tree.config.notify* + nvim-tree |vim.log.levels| + • `ERROR`: hard errors e.g. failure to read from the file system. + • `WARN`: non-fatal errors e.g. unable to system open a file. + • `INFO`: information only e.g. file copy path confirmation. + • `DEBUG`: information for troubleshooting, e.g. failures in some window + closing operations. - When a value is not present/nil, the default will be used. + Fields: ~ + • {threshold}? (`vim.log.levels`, default: `vim.log.levels.INFO`) + Specify minimum notification |vim.log.levels| + • {absolute_path}? (`boolean`, default: `true`) Use absolute paths in + FS action notifications, otherwise item names. - {on_attach} Runs when creating the nvim-tree buffer. Use this to set your - |nvim-tree-mappings|. When not a function, |nvim-tree-mappings-default| - will be used. - {hijack_cursor} keep the cursor on the first letter of the filename when - moving in the tree. - {auto_reload_on_write} reload the explorer every time a buffer is written - to. +============================================================================== +Config: bookmarks *nvim-tree-config-bookmarks* - {disable_netrw} completely disables |netrw|, see |nvim-tree-netrw| for - details. It is strongly advised to eagerly disable netrw, due to race - conditions at vim startup. +*nvim_tree.config.bookmarks* + Optionally {persist} bookmarks to a json file: + • `true` use default: `stdpath("data") .. "/nvim-tree-bookmarks.json"` + • `false` do not persist + • `string` absolute path of your choice - {hijack_netrw} hijacks netrw windows, ignored when {disable_netrw}. + Fields: ~ + • {persist}? (`boolean|string`) (default: `false`) - {hijack_unnamed_buffer_when_opening} opens in place of the unnamed buffer - if it's empty. - {root_dirs} preferred root directories, requires - |nvim_tree.config.update_focused_file.update_root|. - {prefer_startup_root} prefer startup root directory when updating root - directory of the tree. Requires - |nvim_tree.config.update_focused_file.update_root|. +============================================================================== +Config: help *nvim-tree-config-help* - {sync_root_with_cwd} changes the tree root directory on |DirChanged| and - refreshes the tree. +*nvim_tree.config.help* - {reload_on_bufenter} automatically reloads the tree on |BufEnter| - nvim-tree. + Fields: ~ + • {sort_by}? (`"key"|"desc"`, default: `"key"`) Alphabetically. - {respect_buf_cwd} changes the |current-directory| of nvim-tree to that of - new buffer's when opening nvim-tree. - {select_prompts} uses |vim.ui.select()| style prompts. Necessary when - using a UI prompt decorator such as dressing.nvim or - telescope-ui-select.nvim + +============================================================================== +Config: ui *nvim-tree-config-ui* + +*nvim_tree.config.ui* Fields: ~ - • {on_attach}? (`"default"|(fun(bufnr: integer))`) - (default: `default`) - • {hijack_cursor}? (`boolean`) (default: `false`) - • {auto_reload_on_write}? (`boolean`) (default: `true`) - • {disable_netrw}? (`boolean`) (default: `false`) - • {hijack_netrw}? (`boolean`) (default: `true`) - • {hijack_unnamed_buffer_when_opening}? (`boolean`) (default: `false`) - • {root_dirs}? (`string[]`) (default: `{}`) - • {prefer_startup_root}? (`boolean`) (default: `false`) - • {sync_root_with_cwd}? (`boolean`) (default: `false`) - • {reload_on_bufenter}? (`boolean`) (default: `false`) - • {respect_buf_cwd}? (`boolean`) (default: `false`) - • {select_prompts}? (`boolean`) (default: `false`) - • {sort}? (`nvim_tree.config.sort`) - |nvim_tree.config.sort| - • {view}? (`nvim_tree.config.view`) - |nvim_tree.config.view| - • {renderer}? (`nvim_tree.config.renderer`) - |nvim_tree.config.renderer| - • {hijack_directories}? (`nvim_tree.config.hijack_directories`) - |nvim_tree.config.hijack_directories| - • {update_focused_file}? (`nvim_tree.config.update_focused_file`) - |nvim_tree.config.update_focused_file| - • {system_open}? (`nvim_tree.config.system_open`) - |nvim_tree.config.system_open| - • {git}? (`nvim_tree.config.git`) - |nvim_tree.config.git| - • {diagnostics}? (`nvim_tree.config.diagnostics`) - |nvim_tree.config.diagnostics| - • {modified}? (`nvim_tree.config.modified`) - |nvim_tree.config.modified| - • {filters}? (`nvim_tree.config.filters`) - |nvim_tree.config.filters| - • {live_filter}? (`nvim_tree.config.live_filter`) - |nvim_tree.config.live_filter| - • {filesystem_watchers}? (`nvim_tree.config.filesystem_watchers`) - |nvim_tree.config.filesystem_watchers| - • {actions}? (`nvim_tree.config.actions`) - |nvim_tree.config.actions| - • {trash}? (`nvim_tree.config.trash`) - |nvim_tree.config.trash| - • {tab}? (`nvim_tree.config.tab`) - |nvim_tree.config.tab| - • {bookmarks}? (`nvim_tree.config.bookmarks`) - |nvim_tree.config.bookmarks| - • {notify}? (`nvim_tree.config.notify`) - |nvim_tree.config.notify| - • {help}? (`nvim_tree.config.help`) - |nvim_tree.config.help| - • {ui}? (`nvim_tree.config.ui`) - |nvim_tree.config.ui| - • {experimental}? (`nvim_tree.config.experimental`) - |nvim_tree.config.experimental| - • {log}? (`nvim_tree.config.log`) - |nvim_tree.config.log| + • {confirm}? (`nvim_tree.config.ui.confirm`) + |nvim_tree.config.ui.confirm| + +*nvim_tree.config.ui.confirm* + Confirmation prompts. + + Fields: ~ + • {remove}? (`boolean`, default: `true`) Prompt before removing. + • {trash}? (`boolean`, default: `true`) Prompt before trashing. + • {default_yes}? (`boolean`, default: `false`) If `true` the prompt + will be `Y/n`, otherwise `y/N` ============================================================================== -Config: sort *nvim-tree-config-sort* +Config: experimental *nvim-tree-config-experimental* -*nvim_tree.config.sort* - Sort files within a directory. +*nvim_tree.config.experimental* + Experimental features that may become default or optional functionality. - {sorter} presets *nvim_tree.config.sort.Sorter* - • `"name"` - • `"case_sensitive"` name - • `"modification_time"` - • `"extension"` uses all suffixes e.g. `foo.tar.gz` -> `.tar.gz` - • `"suffix"` uses the last e.g. `foo.tar.gz` -> `.gz` - • `"filetype"` |filetype| + In the event of a problem please disable the experiment and raise an + issue. - {sorter} may be a function that is passed a list of `nvim_tree.api.Node` - to be sorted in place e.g. >lua - ---Sort by name length - ---@param nodes nvim_tree.api.Node[] - ---@return nvim_tree.config.sort.Sorter? - local sorter = function(nodes) - table.sort(nodes, function(a, b) - return #a.name < #b.name - end) - end -< - {sorter} may be a function that returns a |nvim_tree.config.sort.Sorter| +============================================================================== +Config: log *nvim-tree-config-log* - Fields: ~ - • {sorter}? (`nvim_tree.config.sort.Sorter|(fun(nodes: nvim_tree.api.Node[]): nvim_tree.config.sort.Sorter?)`) - (default: `"name"`) - • {folders_first}? (`boolean`, default: `true`) Sort folders before - files. Has no effect when {sorter} is a function. - • {files_first}? (`boolean`, default: `false`) Sort files before - folders. Has no effect when {sorter} is a function. - Overrides {folders_first}. +*nvim_tree.config.log* + Log to a file `nvim-tree.log` in |stdpath()| `log`, usually + `${XDG_STATE_HOME}/nvim` + Fields: ~ + • {enable}? (`boolean`) (default: `false`) + • {truncate}? (`boolean`, default: `false`) Remove existing log file at + startup. + • {types}? (`nvim_tree.config.log.types`) + |nvim_tree.config.log.types| +*nvim_tree.config.log.types* + Specify which information to log. -============================================================================== -Config: view *nvim-tree-config-view* + Fields: ~ + • {all}? (`boolean`, default: `false`) Everything. + • {profile}? (`boolean`, default: `false`) Timing of some + operations. + • {config}? (`boolean`, default: `false`) Options and mappings, at + startup. + • {copy_paste}? (`boolean`, default: `false`) File copy and paste + actions. + • {dev}? (`boolean`, default: `false`) Used for local + development only. Not useful for users. + • {diagnostics}? (`boolean`, default: `false`) LSP and COC processing, + verbose. + • {git}? (`boolean`, default: `false`) Git processing, verbose. + • {watcher}? (`boolean`, default: `false`) + |nvim_tree.config.filesystem_watchers| processing, + verbose. -*nvim_tree.config.view* - Configures the dimensions and appearance of the nvim-tree window. - The window is "docked" at the left by default, however may be configured - to float: |nvim_tree.config.view.float| - {width} can be a |nvim_tree.config.view.width.spec| for static control or - a |nvim_tree.config.view.width| for fully dynamic control based on longest - line. +============================================================================== +Config: Default *nvim-tree-config-default* - *nvim_tree.config.view.width.spec* - • `string`: `x%` string e.g. `30%` - • `integer`: number of columns - • `function`: returns one of the above - - Fields: ~ - • {centralize_selection}? (`boolean`, default: `false`) When - entering nvim-tree, reposition the - view so that the current node is - initially centralized, see |zz|. - • {cursorline}? (`boolean`, default: `true`) - |'cursorline'| - • {cursorlineopt}? (`string`, default: `both`) - |'cursorlineopt'| - • {debounce_delay}? (`integer`, default: `15`) Idle - milliseconds before some reload / - refresh operations. Increase if you - experience performance issues around - screen refresh. - • {side}? (`"left"|"right"`) (default: `"left"`) - • {preserve_window_proportions}? (`boolean`, default: `false`) - Preserves window proportions when - opening a file. If `false`, the height - and width of windows other than - nvim-tree will be equalized. - • {number}? (`boolean`, default: `false`) - |'number'| - • {relativenumber}? (`boolean`, default: `false`) - |'relativenumber'| - • {signcolumn}? (`"yes"|"auto"|"no"`, default: - `"yes"`) |'signcolumn'| - • {width}? (`nvim_tree.config.view.width.spec|nvim_tree.config.view.width`) - (default: `30`) - • {float}? (`nvim_tree.config.view.float`) - |nvim_tree.config.view.float| - -*nvim_tree.config.view.float* - Configure floating window behaviour - - {open_win_config} is passed to |nvim_open_win()|, default: >lua - { - relative = "editor", - border = "rounded", - width = 30, - height = 30, - row = 1, - col = 1, - } -< - - Fields: ~ - • {enable}? (`boolean`) (default: `false`) - • {quit_on_focus_loss}? (`boolean`, default: `true`) Close the floating - window when it loses focus. - • {open_win_config}? (`vim.api.keyset.win_config|(fun(): vim.api.keyset.win_config)`) - (default: - `{ relative = "editor", border = "rounded", width = 30, height = 30, row = 1, col = 1, }`) - -*nvim_tree.config.view.width* - Configure dynamic width based on longest line. - - Fields: ~ - • {min}? (`nvim_tree.config.view.width.spec`) (default: - `30`) - • {max}? (`nvim_tree.config.view.width.spec`, default: `-1`) - -1 for unbounded. - • {lines_excluded}? (`("root")[]`, default: `{ "root" }`) Exclude these - lines when computing width. - • {padding}? (`nvim_tree.config.view.width.spec`, default: `1`) - Extra padding to the right. - - - -============================================================================== -Config: renderer *nvim-tree-config-renderer* - -*nvim_tree.config.renderer* - Controls the appearance of the tree. - - See |nvim-tree-icons-highlighting| for {highlight_} and {decorators} - fields. - - {root_folder_label} has 3 forms: - • `string`: |filename-modifiers| format string, default `":~:s?$?/..?"` - • `boolean`: `true` to disable - • `fun(root_cwd: string): string`: return a literal string from root's - absolute path e.g. >lua - my_root_folder_label = function(path) - return ".../" .. vim.fn.fnamemodify(path, ":t") - end -< - - Fields: ~ - • {add_trailing}? (`boolean`, default: `false`) Appends a - trailing slash to folder and symlink folder - target names. - • {group_empty}? (`boolean|(fun(relative_path: string): string)`, default: `false`) - Compact folders that only contain a single - folder into one node. Function variant - takes the relative path of grouped folders - and returns a string to be displayed. - • {full_name}? (`boolean`, default: `false`) Display nodes - whose name length is wider than the width - of nvim-tree window in floating window. - • {root_folder_label}? (`string|boolean|(fun(root_cwd: string): string)`) - (default: `":~:s?$?/..?"`) - • {indent_width}? (`integer`, default: `2`) Number of spaces - for each tree nesting level. Minimum 1. - • {hidden_display}? (`nvim_tree.config.renderer.hidden_display`, default: `none`) - |nvim-tree-hidden-display| - • {symlink_destination}? (`boolean`, default: `true`) Appends an - arrow followed by the target of the - symlink. - • {decorators}? (`(string|nvim_tree.api.decorator.UserDecorator)[]`) - (default: - `{ "Git", "Open", "Hidden", "Modified", "Bookmark", "Diagnostics", "Copied", "Cut", }`) - • {highlight_git}? (`nvim_tree.config.renderer.highlight`) - (default: `"none"`) - • {highlight_opened_files}? (`nvim_tree.config.renderer.highlight`) - (default: `"none"`) - • {highlight_hidden}? (`nvim_tree.config.renderer.highlight`) - (default: `"none"`) - • {highlight_modified}? (`nvim_tree.config.renderer.highlight`) - (default: `"none"`) - • {highlight_bookmarks}? (`nvim_tree.config.renderer.highlight`) - (default: `"none"`) - • {highlight_diagnostics}? (`nvim_tree.config.renderer.highlight`) - (default: `"none"`) - • {highlight_clipboard}? (`nvim_tree.config.renderer.highlight`) - (default: `"name"`) - • {special_files}? (`string[]`, default: `{ "Cargo.toml", "Makefile", "README.md", "readme.md", }`) - Highlight special files and directories - with `NvimTreeSpecial*`. - • {indent_markers}? (`nvim_tree.config.renderer.indent_markers`) - |nvim_tree.config.renderer.indent_markers| - • {icons}? (`nvim_tree.config.renderer.icons`) - |nvim_tree.config.renderer.icons| - -*nvim_tree.config.renderer.icons* - Icons and separators - - See |nvim-tree-icons-highlighting| for: {_placement} fields. - - Fields: ~ - • {git_placement}? (`nvim_tree.config.renderer.icons.placement`) - (default: `before`) - • {hidden_placement}? (`nvim_tree.config.renderer.icons.placement`) - (default: `after`) - • {modified_placement}? (`nvim_tree.config.renderer.icons.placement`) - (default: `after`) - • {bookmarks_placement}? (`nvim_tree.config.renderer.icons.placement`) - (default: `signcolumn`) - • {diagnostics_placement}? (`nvim_tree.config.renderer.icons.placement`) - (default: `signcolumn`) - • {padding}? (`table`) - *nvim_tree.config.renderer.icons.padding* - • {icon}? (`string`, default: `" "`) Between - icon and filename. - • {folder_arrow}? (`string`, default: `" "`) - Between folder arrow icon and file/folder - icon. - • {symlink_arrow}? (`string`, default: `" ➛ "`) Separator - between symlink source and target. - • {show}? (`nvim_tree.config.renderer.icons.show`) - |nvim_tree.config.renderer.icons.show| - • {glyphs}? (`nvim_tree.config.renderer.icons.glyphs`) - |nvim_tree.config.renderer.icons.glyphs| - • {web_devicons}? (`nvim_tree.config.renderer.icons.web_devicons`) - |nvim_tree.config.renderer.icons.web_devicons| - -*nvim_tree.config.renderer.icons.glyphs* - See |nvim-tree-icons-highlighting|. - - Glyphs that appear in the sign column must have length <= 2 - - Fields: ~ - • {default}? (`string`, default: `""`) Files - • {symlink}? (`string`) (default: `""`) - • {bookmark}? (`string`) (default: `"󰆤"`) - • {modified}? (`string`) (default: `"●"`) - • {hidden}? (`string`) (default: `"󰜌"`) - • {folder}? (`table`) *nvim_tree.config.renderer.icons.glyphs.folder* - • {arrow_closed}? (`string`) (default: left arrow) - • {arrow_open}? (`string`) (default: down arrow) - • {default}? (`string`) (default: `""`) - • {open}? (`string`) (default: `""`) - • {empty}? (`string`) (default: `""`) - • {empty_open}? (`string`) (default: `""`) - • {symlink}? (`string`) (default: `""`) - • {symlink_open}? (`string`) (default: `""`) - • {git}? (`table`) *nvim_tree.config.renderer.icons.glyphs.git* - • {unstaged}? (`string`) (default: `"✗"`) - • {staged}? (`string`) (default: `"✓"`) - • {unmerged}? (`string`) (default: `""`) - • {renamed}? (`string`) (default: `"➜"`) - • {untracked}? (`string`) (default: `"★"`) - • {deleted}? (`string`) (default: `""`) - • {ignored}? (`string`) (default: `"◌"`) - -*nvim_tree.config.renderer.icons.show* - See |nvim-tree-icons-highlighting|. - - Fields: ~ - • {file}? (`boolean`) (default: `true`) - • {folder}? (`boolean`) (default: `true`) - • {git}? (`boolean`) (default: `true`) - • {modified}? (`boolean`) (default: `true`) - • {hidden}? (`boolean`) (default: `false`) - • {diagnostics}? (`boolean`) (default: `true`) - • {bookmarks}? (`boolean`) (default: `true`) - • {folder_arrow}? (`boolean`, default: `true`) Show a small arrow - before the folder node. Arrow will be a part of the - node when using - |nvim_tree.config.renderer.indent_markers|. - -*nvim_tree.config.renderer.icons.web_devicons* - Configure optional plugin `nvim-tree/nvim-web-devicons`, see - |nvim-tree-icons-highlighting|. - - Fields: ~ - • {file}? (`table`) - *nvim_tree.config.renderer.icons.web_devicons.file* - • {enable}? (`boolean`) (default: `true`) - • {color}? (`boolean`) (default: `true`) - • {folder}? (`table`) - *nvim_tree.config.renderer.icons.web_devicons.folder* - • {enable}? (`boolean`) (default: `false`) - • {color}? (`boolean`) (default: `true`) - -*nvim_tree.config.renderer.indent_markers* - - Fields: ~ - • {enable}? (`boolean`, default: `false`) Display indent markers - when folders are open. - • {inline_arrows}? (`boolean`, default: `true`) Display folder arrows - in the same column as indent marker when using - |nvim_tree.config.renderer.icons.padding| - {folder_arrow} - • {icons}? (`table`) - *nvim_tree.config.renderer.indent_markers.icons* - Before the file/directory, length 1. - • {corner}? (`string`) (default: `"└"`) - • {edge}? (`string`) (default: `"│"`) - • {item}? (`string`) (default: `"│"`) - • {bottom}? (`string`) (default: `"─"`) - • {none}? (`string`) (default: `" "`) - - - -============================================================================== -Config: hijack_directories *nvim-tree-config-hijack-directories* - -*nvim_tree.config.hijack_directories* - Hijack directory buffers by replacing the directory buffer with the tree. - - Disable this option if you use vim-dirvish or dirbuf.nvim. - - If |nvim_tree.config| {hijack_netrw} and {disable_netrw} are `false` this - feature will be disabled. - - Fields: ~ - • {enable}? (`boolean`) (default: `true`) - • {auto_open}? (`boolean`, default: `true`) Open if the tree was - previously closed. - - - -============================================================================== -Config: update_focused_file *nvim-tree-config-update-focused-file* - -*nvim_tree.config.update_focused_file* - Update the focused file on |BufEnter|, uncollapsing folders recursively. - - Fields: ~ - • {enable}? (`boolean`) (default: `false`) - • {update_root}? (`nvim_tree.config.update_focused_file.update_root`) - |nvim_tree.config.update_focused_file.update_root| - • {exclude}? (`boolean|(fun(args: vim.api.keyset.create_autocmd.callback_args): boolean)`, default: `false`) - A function called on |BufEnter| that returns true if - the file should not be focused when opening. - -*nvim_tree.config.update_focused_file.update_root* - Update the root directory of the tree if the file is not under the current - root directory. - - Prefers vim's cwd and |nvim_tree.config| {root_dirs}, falling back to the - directory containing the file. - - Requires |nvim_tree.config.update_focused_file| - - Fields: ~ - • {enable}? (`boolean`) (default: `false`) - • {ignore_list}? (`string[]`, default: `{}`) List of buffer names and - filetypes that will not update the root dir of the - tree if the file isn't found under the current root - directory. - - - -============================================================================== -Config: system_open *nvim-tree-config-system-open* - -*nvim_tree.config.system_open* - Open files or directories via the OS. - - Nvim: - • `>=` 0.10 uses |vim.ui.open()| unless {cmd} is specified - • `<` 0.10 calls external {cmd}: - • UNIX: `xdg-open` - • macOS: `open` - • Windows: `cmd` - - Once nvim-tree minimum Nvim version is updated to 0.10, these options will - no longer be necessary and will be removed. - - Fields: ~ - • {cmd}? (`string`) The open command itself - • {args}? (`string[]`, default: `{}` or `{ "/c", "start", '""' }` on - windows) Optional argument list. Leave empty for OS specific - default. - - - -============================================================================== -Config: git *nvim-tree-config-git* - -*nvim_tree.config.git* - Git operations are run in the background thus status may not immediately - appear. - - Processes will be killed if they exceed {timeout} ms. Git integration will - be disabled following 5 timeouts and you will be notified. - - Git integration may be disabled for git top-level directories via - {disable_for_dirs}: - • A list of relative paths evaluated with |fnamemodify()| `:p` OR - • A function that is passed an absolute path and returns `true` to disable - - See |nvim-tree-icons-highlighting|. - - Fields: ~ - • {enable}? (`boolean`) (default: `true`) - • {show_on_dirs}? (`boolean`, default: `true`) Show status icons - of children when directory itself has no status - icon - • {show_on_open_dirs}? (`boolean`, default: `true`) Show status icons - of children on directories that are open. - Requires {show_on_dirs}. - • {disable_for_dirs}? (`string[]|(fun(path: string): boolean)`, - default: `{}`) Disable for top level paths. - • {timeout}? (`integer`, default: `400`) `git` processes - timeout milliseconds. - • {cygwin_support}? (`boolean`, default: `false`) Use `cygpath` if - available to resolve paths for git. - - - -============================================================================== -Config: diagnostics *nvim-tree-config-diagnostics* - -*nvim_tree.config.diagnostics* - Integrate with |lsp| or COC diagnostics. - - See |nvim-tree-icons-highlighting|. - - Fields: ~ - • {enable}? (`boolean`) (default: `false`) - • {debounce_delay}? (`integer`, default: `500`) Idle milliseconds - between diagnostic event and tree update. - • {show_on_dirs}? (`boolean`, default: `false`) Show diagnostic - icons on parent directories. - • {show_on_open_dirs}? (`boolean`, default: `true`) Show diagnostics - icons on directories that are open. Requires - {show_on_dirs}. - • {diagnostic_opts}? (`boolean`, default: `false`) Global - |vim.diagnostic.Opts| overrides {severity} and - {icons} - • {severity}? (`table`) - *nvim_tree.config.diagnostics.severity* - • {min}? (`vim.diagnostic.Severity`, default: - HINT) |vim.diagnostic.severity| - • {max}? (`vim.diagnostic.Severity`, default: - ERROR) |vim.diagnostic.severity| - • {icons}? (`table`) *nvim_tree.config.diagnostics.icons* - • {hint}? (`string`) (default: `""` ) - • {info}? (`string`) (default: `""` ) - • {warning}? (`string`) (default: `""` ) - • {error}? (`string`) (default: `""` ) - - - -============================================================================== -Config: modified *nvim-tree-config-modified* - -*nvim_tree.config.modified* - Indicate which files have unsaved modification. To see modified status in - the tree you will need: - • |nvim_tree.config.renderer.icons.show| {modified} OR - • |nvim_tree.config.renderer| {highlight_modified} - - See |nvim-tree-icons-highlighting|. - - Fields: ~ - • {enable}? (`boolean`) (default: `false`) - • {show_on_dirs}? (`boolean`, default: `true`) Show modified - indication on directory whose children are - modified. - • {show_on_open_dirs}? (`boolean`, default: `false`) Show modified - indication on open directories. Requires - {show_on_dirs}. - - - -============================================================================== -Config: filters *nvim-tree-config-filters* - -*nvim_tree.config.filters* - Filters may be applied to the tree to exlude the display of - file/directories. - - Multiple filters may be applied at once. - - Filters can be set at startup or toggled live via API with default - mappings. - - `I `{git_ignored}` `|nvim-tree-api.tree.toggle_gitignore_filter()| - Ignore files based on `.gitignore`. Requires |nvim_tree.config.git| - - `H `{dotfiles}` `|nvim-tree-api.tree.toggle_hidden_filter()| - Filter dotfiles: files/directories starting with a `.` - - `C `{git_clean}` `|nvim-tree-api.tree.toggle_git_clean_filter()| - Filter files with no git status. `.gitignore` files will not be filtered - when {git_ignored}, as they are effectively dirty. - - `B `{no_buffer}` `|nvim-tree-api.tree.toggle_no_buffer_filter()| - Filter files that have no |buflisted()| buffer. For performance reasons - buffer delete/wipe may not be immediately shown. A reload or filesystem - event will always result in an update. - - `M `{no_bookmark}` `|nvim-tree-api.tree.toggle_no_bookmark_filter()| - Filter files that are not bookmarked. Enabling this is not useful as there - is no means yet to persist bookmarks. - - `U `{custom}` `|nvim-tree-api.tree.toggle_custom_filter()| - Disable specific file/directory names via: - • a list of backslash escaped |vim.regex| strings e.g. `"^\\.git""` - • a function passed the absolute path of the directory. - - All filters including live filter may be disabled via {enable} and toggled - with |nvim-tree-api.tree.toggle_enable_filters()| - - Files/directories may be {exclude}d from filtering: they will always be - shown, overriding {git_ignored}, {dotfiles} and {custom}. - - Fields: ~ - • {enable}? (`boolean`, default: `true`) Enable all filters. - • {git_ignored}? (`boolean`) (default: `true`) - • {dotfiles}? (`boolean`) (default: `false`) - • {git_clean}? (`boolean`) (default: `false`) - • {no_buffer}? (`boolean`) (default: `false`) - • {no_bookmark}? (`boolean`) (default: `false`) - • {custom}? (`string[]|(fun(absolute_path: string): boolean)`) - (default: `{}`) - • {exclude}? (`string[]`) (default: `{}`) - - - -============================================================================== -Config: live_filter *nvim-tree-config-live-filter* - -*nvim_tree.config.live_filter* - Live filter allows you to filter the tree nodes dynamically, based on - regex matching, see |vim.regex| - - This feature is bound to the `f` key by default. The filter can be cleared - with the `F` key by default. - - Fields: ~ - • {prefix}? (`string`, default: `"[FILTER]: "`) Prefix of - the filter displayed in the buffer. - • {always_show_folders}? (`boolean`, default: `true`) Whether to filter - folders or not. - - - -============================================================================== -Config: filesystem_watchers *nvim-tree-config-filesystem-watchers* - -*nvim_tree.config.filesystem_watchers* - Use file system watchers (libuv `uv_fs_event_t`) to monitor the filesystem - for changes and update the tree. - - With this feature, the tree will be partially updated on specific - directory changes, resulting in better performance. - - Watchers may be disabled for absolute directory paths via {ignore_dirs}. - • A list of |vim.regex| to match a path, backslash escaped e.g. - `"my-proj/\\.build$"` OR - • A function that is passed an absolute path and returns `true` to disable - This may be useful when a path is not in `.gitignore` or git integration - is disabled. - - After {max_events} consecutive filesystem events on a single directory - with an interval < {debounce_delay}: - • The filesystem watcher will be disabled for that directory. - • A warning notification will be shown. - • Consider adding this directory to {ignore_dirs} - - Fields: ~ - • {enable}? (`boolean`) (default: `true`) - • {debounce_delay}? (`integer`, default: `50`) Idle milliseconds - between filesystem change and tree update. - • {ignore_dirs}? (`string[]|(fun(path: string): boolean)`, default: `{ "/.ccls-cache", "/build", "/node_modules", "/target", }`) - Disable for specific directories. - • {max_events}? (`integer`, default: `100`) Disable for a single - directory after {max_events} consecutive events - with an interval < {debounce_delay}. - - - -============================================================================== -Config: actions *nvim-tree-config-actions* - -*nvim_tree.config.actions* - - Fields: ~ - • {use_system_clipboard}? (`boolean`, default: `true`) Use the system - clipboard for copy/paste. Copied text will be - stored in registers `+` (system), otherwise, - it will be stored in `1` and `"` - • {change_dir}? (`nvim_tree.config.actions.change_dir`) - |nvim_tree.config.actions.change_dir| - • {expand_all}? (`nvim_tree.config.actions.expand_all`) - |nvim_tree.config.actions.expand_all| - • {file_popup}? (`nvim_tree.config.actions.file_popup`) - |nvim_tree.config.actions.file_popup| - • {open_file}? (`nvim_tree.config.actions.open_file`) - |nvim_tree.config.actions.open_file| - • {remove_file}? (`nvim_tree.config.actions.remove_file`) - |nvim_tree.config.actions.remove_file| - -*nvim_tree.config.actions.change_dir* - vim |current-directory| behaviour - - Fields: ~ - • {enable}? (`boolean`, default: `true`) Change the working - directory when changing directories in the tree - • {global}? (`boolean`, default: `false`) Use `:cd` instead - of `:lcd` when changing directories. - • {restrict_above_cwd}? (`boolean`, default: `false`) Restrict changing - to a directory above the global cwd. - -*nvim_tree.config.actions.expand_all* - Configure |nvim-tree-api.tree.expand_all()| and - |nvim-tree-api.node.expand()| - - Fields: ~ - • {max_folder_discovery}? (`integer`, default: `300`) Limit the number - of folders being explored when expanding - every folder. Avoids hanging Nvim when - running this action on very large folders. - • {exclude}? (`string[]`, default: `{}`) A list of - directories that should not be expanded - automatically e.g - `{ ".git", "target", "build" }` - -*nvim_tree.config.actions.file_popup* - {file_popup} floating window. - - {open_win_config} is passed to |nvim_open_win()|, default: >lua - { - col = 1, - row = 1, - relative = "cursor", - border = "shadow", - style = "minimal", - } -< - - You shouldn't define {width} and {height} values here. They will be - overridden to fit the file_popup content. - - Fields: ~ - • {open_win_config}? (`vim.api.keyset.win_config`) (default: - `{ col = 1, row = 1, relative = "cursor", border = "shadow", style = "minimal", }`) - -*nvim_tree.config.actions.open_file* - Opening files. - - Fields: ~ - • {quit_on_open}? (`boolean`, default: `false`) Closes the explorer - when opening a file - • {eject}? (`boolean`, default: `true`) Prevent new opened file - from opening in the same window as the tree. - • {resize_window}? (`boolean`, default: `true`) Resizes the tree when - opening a file - • {window_picker}? (`nvim_tree.config.actions.open_file.window_picker`) - |nvim_tree.config.actions.open_file.window_picker| - -*nvim_tree.config.actions.open_file.window_picker* - A window picker will be shown when there are multiple windows available to - open a file. It will show a single character identifier in each window's - status line. - - When it is not enabled the file will open in the window from which you - last opened the tree, obeying {exclude} - - You may define a {picker} function that should return the window id that - will open the node, or `nil` if an invalid window is picked or user - cancelled the action. The picker may create a new window. - - Fields: ~ - • {enable}? (`boolean`) (default: `true`) - • {picker}? (`"default"|(fun(): integer)`, default: `"default"`) - Change the default window picker or define your own. - • {chars}? (`string`, default: - `"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"`) Identifier - characters to use. - • {exclude}? (`nvim_tree.config.actions.open_file.window_picker.exclude`) - |nvim_tree.config.actions.open_file.window_picker.exclude| - -*nvim_tree.config.actions.open_file.window_picker.exclude* - Tables of buffer option names mapped to a list of option values. Windows - containing matching buffers will not be: - • available when using a window picker - • selected when not using a window picker - - Fields: ~ - • {filetype}? (`string[]`) (default: - `{ "notify", "lazy", "qf", "diff", "fugitive", "fugitiveblame", }`) - • {buftype}? (`string[]`) (default: - `{ "nofile", "terminal", "help", }`) - -*nvim_tree.config.actions.remove_file* - Removing files. - - Fields: ~ - • {close_window}? (`boolean`, default: `true`) Close any window that - displays a file when removing that file from the - tree. - - - -============================================================================== -Config: trash *nvim-tree-config-trash* - -*nvim_tree.config.trash* - Files may be trashed via an external command that must be installed on - your system. - • linux: `gio trash`, from linux package `glib2` - • macOS: `trash`, from homebrew package `trash` - • windows: `trash`, requires `trash-cli` or similar - - Fields: ~ - • {cmd}? (`string`) (default: `"gio trash"` or `"trash"`) - - - -============================================================================== -Config: tab *nvim-tree-config-tab* - -*nvim_tree.config.tab* - - Fields: ~ - • {sync}? (`nvim_tree.config.tab.sync`) |nvim_tree.config.tab.sync| - -*nvim_tree.config.tab.sync* - - Fields: ~ - • {open}? (`boolean`, default: `false`) Opens the tree automatically - when switching tabpage or opening a new tabpage if the tree - was previously open. - • {close}? (`boolean`, default: `false`) Closes the tree across all - tabpages when the tree is closed. - • {ignore}? (`string[]`, default: `{}`) List of filetypes or buffer - names on new tab that will prevent `open` and `close` - - - -============================================================================== -Config: notify *nvim-tree-config-notify* - -*nvim_tree.config.notify* - nvim-tree |vim.log.levels| - • `ERROR`: hard errors e.g. failure to read from the file system. - • `WARN`: non-fatal errors e.g. unable to system open a file. - • `INFO`: information only e.g. file copy path confirmation. - • `DEBUG`: information for troubleshooting, e.g. failures in some window - closing operations. - - Fields: ~ - • {threshold}? (`vim.log.levels`, default: `vim.log.levels.INFO`) - Specify minimum notification |vim.log.levels| - • {absolute_path}? (`boolean`, default: `true`) Use absolute paths in - FS action notifications, otherwise item names. - - - -============================================================================== -Config: bookmarks *nvim-tree-config-bookmarks* - -*nvim_tree.config.bookmarks* - Optionally {persist} bookmarks to a json file: - • `true` use default: `stdpath("data") .. "/nvim-tree-bookmarks.json"` - • `false` do not persist - • `string` absolute path of your choice - - Fields: ~ - • {persist}? (`boolean|string`) (default: `false`) - - - -============================================================================== -Config: help *nvim-tree-config-help* - -*nvim_tree.config.help* - - Fields: ~ - • {sort_by}? (`"key"|"desc"`, default: `"key"`) Alphabetically. - - - -============================================================================== -Config: ui *nvim-tree-config-ui* - -*nvim_tree.config.ui* - - Fields: ~ - • {confirm}? (`nvim_tree.config.ui.confirm`) - |nvim_tree.config.ui.confirm| - -*nvim_tree.config.ui.confirm* - Confirmation prompts. - - Fields: ~ - • {remove}? (`boolean`, default: `true`) Prompt before removing. - • {trash}? (`boolean`, default: `true`) Prompt before trashing. - • {default_yes}? (`boolean`, default: `false`) If `true` the prompt - will be `Y/n`, otherwise `y/N` - - - -============================================================================== -Config: experimental *nvim-tree-config-experimental* - -*nvim_tree.config.experimental* - Experimental features that may become default or optional functionality. - - In the event of a problem please disable the experiment and raise an - issue. - - - -============================================================================== -Config: log *nvim-tree-config-log* - -*nvim_tree.config.log* - Log to a file `nvim-tree.log` in |stdpath()| `log`, usually - `${XDG_STATE_HOME}/nvim` - - Fields: ~ - • {enable}? (`boolean`) (default: `false`) - • {truncate}? (`boolean`, default: `false`) Remove existing log file at - startup. - • {types}? (`nvim_tree.config.log.types`) - |nvim_tree.config.log.types| - -*nvim_tree.config.log.types* - Specify which information to log. - - Fields: ~ - • {all}? (`boolean`, default: `false`) Everything. - • {profile}? (`boolean`, default: `false`) Timing of some - operations. - • {config}? (`boolean`, default: `false`) Options and mappings, at - startup. - • {copy_paste}? (`boolean`, default: `false`) File copy and paste - actions. - • {dev}? (`boolean`, default: `false`) Used for local - development only. Not useful for users. - • {diagnostics}? (`boolean`, default: `false`) LSP and COC processing, - verbose. - • {git}? (`boolean`, default: `false`) Git processing, verbose. - • {watcher}? (`boolean`, default: `false`) - |nvim_tree.config.filesystem_watchers| processing, - verbose. - - - -============================================================================== -Config: Default *nvim-tree-default-config* - -Following is the default configuration, see |nvim_tree.config| for details. >lua +Following is the default configuration, see |nvim_tree.config| for details. >lua ---@type nvim_tree.config local config = { @@ -3095,4 +2369,840 @@ Following is the default configuration, see |nvim_tree.config| for details. >lua +============================================================================== +API *nvim-tree-api* + +nvim-tree exposes a public API. This is non breaking, with additions made as +necessary. + +Please do not require or use modules other than `nvim-tree.api`, as internal +modules will change without notice. + +The API is separated into multiple modules: +• |nvim-tree-api-commands| +• |nvim-tree-api-events| +• |nvim-tree-api-filter| +• |nvim-tree-api-fs| +• |nvim-tree-api-git| +• |nvim-tree-api-health| +• |nvim-tree-api-map| +• |nvim-tree-api-marks| +• |nvim-tree-api-node| +• |nvim-tree-api-tree| + +Modules are accessed via `api..` + +Example invocation of the `reload` function in the `tree` module: >lua + + local api = require("nvim-tree.api") + api.tree.reload() +< + +Generally, functions accepting a |nvim_tree.api.Node| as their first argument +will use the node under the cursor when that argument is not present or nil. +e.g. the following are functionally identical: >lua + + api.node.open.edit(nil, { focus = true }) + + api.node.open.edit(api.tree.get_node_under_cursor(), { focus = true }) +< + + +*nvim_tree.api.Node* + The Node class is a data class. Instances may be provided by API functions + for use as a: + • handle to pass back to API functions e.g. |nvim_tree.api.node.run.cmd()| + • reference in callbacks e.g. |nvim_tree.config.sort.Sorter| {sorter} + + Please do not mutate the contents of any Node object. + + Fields: ~ + • {absolute_path} (`string`) of the file or directory + • {name} (`string`) file or directory name + • {parent}? (`nvim_tree.api.DirectoryNode`) parent directory, + nil for root + • {type} (`"file"|"directory"|"link"`) |uv.fs_stat()| {type} + • {executable} (`boolean`) file is executable + • {fs_stat}? (`uv.fs_stat.result`) at time of last tree display, + see |uv.fs_stat()| + • {git_status} (`nvim_tree.git.Status?`) for files and directories + • {diag_severity}? (`lsp.DiagnosticSeverity`) diagnostic status + • {hidden} (`boolean`) node is not visible in the tree + +*nvim_tree.git.Status* + Git statuses for a single node. + + `nvim_tree.git.XY`: 2 character string, see `man 1 git-status` "Short + Format" + + {dir} status is derived from its contents: + • `direct`: inherited from child files + • `indirect`: inherited from child directories + + Fields: ~ + • {file}? (`nvim_tree.git.XY`) status of a file node + • {dir}? (`table<"direct"|"indirect", nvim_tree.git.XY[]>`) direct + inclusive-or indirect status + + + +============================================================================== +API: commands *nvim-tree-api-commands* + +get() *nvim_tree.api.commands.get()* + Retrieve all |nvim-tree-commands| + + They have been created via |nvim_create_user_command()|, see also + |lua-guide-commands-create| + + Return: ~ + (`table[]`) + • {name} (`string`) name of the `:NvimTree*` command + • {command} + (`fun(args: vim.api.keyset.create_user_command.command_args)`) + function that the command will execute + • {opts} (`vim.api.keyset.user_command`) |command-attributes| + + +============================================================================== +API: events *nvim-tree-api-events* + +subscribe({event_type}, {callback}) *nvim_tree.api.events.subscribe()* + Register a handler for an event, see |nvim-tree-events|. + + Parameters: ~ + • {event_type} (`string`) |nvim_tree_events_kind| + • {callback} (`fun(payload: table?)`) + + +============================================================================== +API: filter *nvim-tree-api-filter* + +custom.toggle() *nvim_tree.api.filter.custom.toggle()* + Toggle |nvim_tree.config.filters| {custom} filter. + +dotfiles.toggle() *nvim_tree.api.filter.dotfiles.toggle()* + Toggle |nvim_tree.config.filters| {dotfiles} filter. + +git.clean.toggle() *nvim_tree.api.filter.git.clean.toggle()* + Toggle |nvim_tree.config.filters| {git_clean} filter. + +git.ignored.toggle() *nvim_tree.api.filter.git.ignored.toggle()* + Toggle |nvim_tree.config.filters| {git_ignored} filter. + +live.clear() *nvim_tree.api.filter.live.clear()* + Exit live filter mode. + +live.start() *nvim_tree.api.filter.live.start()* + Enter live filter mode. Opens an input window with |filetype| + `NvimTreeFilter` + +no_bookmark.toggle() *nvim_tree.api.filter.no_bookmark.toggle()* + Toggle |nvim_tree.config.filters| {no_bookmark} filter. + +no_buffer.toggle() *nvim_tree.api.filter.no_buffer.toggle()* + Toggle |nvim_tree.config.filters| {no_buffer} filter. + +toggle() *nvim_tree.api.filter.toggle()* + Toggle |nvim_tree.config.filters| {enable} which applies to ALL filters. + + +============================================================================== +API: fs *nvim-tree-api-fs* + +clear_clipboard() *nvim_tree.api.fs.clear_clipboard()* + Clear the nvim-tree clipboard. + +copy.absolute_path({node}) *nvim_tree.api.fs.copy.absolute_path()* + Copy the absolute path to the system clipboard. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +copy.basename({node}) *nvim_tree.api.fs.copy.basename()* + Copy the name with extension omitted to the system clipboard. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +copy.filename({node}) *nvim_tree.api.fs.copy.filename()* + Copy the name to the system clipboard. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +copy.node({node}) *nvim_tree.api.fs.copy.node()* + Copy to the nvim-tree clipboard. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +copy.relative_path({node}) *nvim_tree.api.fs.copy.relative_path()* + Copy the path relative to the tree root to the system clipboard. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +create({node}) *nvim_tree.api.fs.create()* + Prompt to create a file or directory. + + When {node} is a file it will be created in the parent directory. + + Use a trailing `"/"` to create a directory e.g. `"foo/"` + + Multiple directories/files may be created e.g. `"foo/bar/baz"` + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +cut({node}) *nvim_tree.api.fs.cut()* + Cut to the nvim-tree clipboard. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +paste({node}) *nvim_tree.api.fs.paste()* + Paste from the nvim-tree clipboard. + + If {node} is a file it will pasted in the parent directory. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +print_clipboard() *nvim_tree.api.fs.print_clipboard()* + Print the contents of the nvim-tree clipboard. + +remove({node}) *nvim_tree.api.fs.remove()* + Delete from the file system. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +rename({node}) *nvim_tree.api.fs.rename()* + Prompt to rename by name. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +rename_basename({node}) *nvim_tree.api.fs.rename_basename()* + Prompt to rename by name with extension omitted. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +rename_full({node}) *nvim_tree.api.fs.rename_full()* + Prompt to rename by absolute path. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +rename_node({node}) *nvim_tree.api.fs.rename_node()* + Prompt to rename. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +rename_sub({node}) *nvim_tree.api.fs.rename_sub()* + Prompt to rename by absolute path with name omitted. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + +trash({node}) *nvim_tree.api.fs.trash()* + Trash as per |nvim_tree.config.trash| + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) + + +============================================================================== +API: git *nvim-tree-api-git* + + *nvim_tree.api._git.nvim_tree.api.git.reload()* +nvim_tree.api.git.reload() + Update the git status of the entire tree. + + +============================================================================== +API: health *nvim-tree-api-health* + +hi_test() *nvim_tree.api.health.hi_test()* + Open a new buffer displaying all nvim-tree highlight groups, their link + chain and concrete definition. + + Similar to `:so $VIMRUNTIME/syntax/hitest.vim` as per |:highlight| + + +============================================================================== +API: map *nvim-tree-api-map* + +keymap.current() *nvim_tree.api.map.keymap.current()* + Retrieve all buffer local mappings for nvim-tree. These are the mappings + that are applied by |nvim_tree.config| {on_attach}, which may include + default mappings. + + Return: ~ + (`vim.api.keyset.get_keymap[]`) + +keymap.default() *nvim_tree.api.map.keymap.default()* + Retrieves the buffer local mappings for nvim-tree that are applied by + |nvim_tree.api.map.on_attach.default()| + + Return: ~ + (`vim.api.keyset.get_keymap[]`) + +on_attach.default({bufnr}) *nvim_tree.api.map.on_attach.default()* + Apply all |nvim-tree-mappings-default|. Call from your |nvim_tree.config| + {on_attach}. + + Parameters: ~ + • {bufnr} (`integer`) use the `bufnr` passed to {on_attach} + + +============================================================================== +API: marks *nvim-tree-api-marks* + +bulk.delete() *nvim_tree.api.marks.bulk.delete()* + Delete all marked, prompting if |nvim_tree.config.ui.confirm| {remove} + +bulk.move() *nvim_tree.api.marks.bulk.move()* + Prompts for a directory to move all marked nodes into. + +bulk.trash() *nvim_tree.api.marks.bulk.trash()* + Delete all marked, prompting if |nvim_tree.config.ui.confirm| {trash} + +clear() *nvim_tree.api.marks.clear()* + Clear all marks. + +get() *nvim_tree.api.marks.get()* + Return the node if it is marked. + + Return: ~ + (`nvim_tree.api.Node?`) + +list() *nvim_tree.api.marks.list()* + Retrieve all marked nodes. + + Return: ~ + (`nvim_tree.api.Node[]`) + +navigate.next() *nvim_tree.api.marks.navigate.next()* + Navigate to the next marked node, wraps. + +navigate.prev() *nvim_tree.api.marks.navigate.prev()* + Navigate to the previous marked node, wraps. + +navigate.select() *nvim_tree.api.marks.navigate.select()* + Prompts for selection of a marked node, sorted by absolute paths. A folder + will be focused, a file will be opened. + +toggle({node}) *nvim_tree.api.marks.toggle()* + Toggle mark. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) file or directory + + +============================================================================== +API: node *nvim-tree-api-node* + +buffer.delete({node}, {opts}) *nvim_tree.api.node.buffer.delete()* + Deletes node's related buffer, if one exists. Executes |:bdelete| or + |:bdelete|! + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) file + • {opts} (`table?`) + • {force}? (`boolean`, default: false) Proceed even if the + buffer is modified. + +buffer.wipe({node}, {opts}) *nvim_tree.api.node.buffer.wipe()* + Wipes node's related buffer, if one exists. Executes |:bwipe| or |:bwipe|! + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) file + • {opts} (`table?`) optional + • {force}? (`boolean`, default: false) Proceed even if the + buffer is modified. + +collapse({node}, {opts}) *nvim_tree.api.node.collapse()* + Collapse the tree under a directory or a file's parent directory. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + • {opts} (`table?`) optional + • {keep_buffers}? (`boolean`, default: false) Do not collapse + nodes with open buffers. + +expand({node}, {opts}) *nvim_tree.api.node.expand()* + Recursively expand all nodes under a directory or a file's parent + directory. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + • {opts} (`table?`) optional + • {expand_until}? + (`fun(expansion_count: integer, node: Node): boolean`) + Return `true` if `node` should be expanded. + `expansion_count` is the total number of folders expanded. + + *nvim_tree.api.node.navigate.diagnostics.next()* +navigate.diagnostics.next({node}) + Navigate to the next item showing diagnostic status. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.diagnostics.next_recursive()* +navigate.diagnostics.next_recursive({node}) + Navigate to the next item showing diagnostic status, recursively. Needs + |nvim_tree.config.diagnostics| {show_on_dirs} + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.diagnostics.prev()* +navigate.diagnostics.prev({node}) + Navigate to the previous item showing diagnostic status. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.diagnostics.prev_recursive()* +navigate.diagnostics.prev_recursive({node}) + Navigate to the previous item showing diagnostic status, recursively. + Needs |nvim_tree.config.diagnostics| {show_on_dirs} + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + +navigate.git.next({node}) *nvim_tree.api.node.navigate.git.next()* + Navigate to the next item showing git status. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.git.next_recursive()* +navigate.git.next_recursive({node}) + Navigate to the next item showing git status, recursively. Needs + |nvim_tree.config.git| {show_on_dirs} + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.git.next_skip_gitignored()* +navigate.git.next_skip_gitignored({node}) + Navigate to the next item showing git status, skipping `.gitignore` + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + +navigate.git.prev({node}) *nvim_tree.api.node.navigate.git.prev()* + Navigate to the previous item showing git status. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.git.prev_recursive()* +navigate.git.prev_recursive({node}) + Navigate to the previous item showing git status, recursively. Needs + |nvim_tree.config.git| {show_on_dirs} + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.git.prev_skip_gitignored()* +navigate.git.prev_skip_gitignored({node}) + Navigate to the previous item showing git status, skipping `.gitignore` + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.opened.next()* +navigate.opened.next({node}) + Navigate to the next |bufloaded()| file. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.opened.prev()* +navigate.opened.prev({node}) + Navigate to the previous |bufloaded()| file. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + +navigate.parent({node}) *nvim_tree.api.node.navigate.parent()* + Navigate to the parent directory of the node. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.parent_close()* +navigate.parent_close({node}) + Navigate to the parent directory of the node, closing it. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.sibling.first()* +navigate.sibling.first({node}) + Navigate to the first node in the current node's folder. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.sibling.last()* +navigate.sibling.last({node}) + Navigate to the last node in the current node's folder. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.sibling.next()* +navigate.sibling.next({node}) + Navigate to the next node in the current node's folder, wraps. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.navigate.sibling.prev()* +navigate.sibling.prev({node}) + Navigate to the previous node in the current node's folder, wraps. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + +open.edit({node}, {opts}) *nvim_tree.api.node.open.edit()* + • file: open as per |nvim_tree.config.actions.open_file| + • directory: expand or collapse + • root: change directory up + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + • {opts} (`table?`) optional + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. + • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + +open.horizontal({node}, {opts}) *nvim_tree.api.node.open.horizontal()* + Open file in a new horizontal split. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) file + • {opts} (`table?`) optional + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. + • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + + *nvim_tree.api.node.open.horizontal_no_picker()* +open.horizontal_no_picker({node}, {opts}) + Open file in a new horizontal split without using the window picker. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) file + • {opts} (`table?`) optional + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. + • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + + *nvim_tree.api.node.open.no_window_picker()* +open.no_window_picker({node}, {opts}) + Open file without using the window picker. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) file + • {opts} (`table?`) optional + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. + • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + +open.preview({node}, {opts}) *nvim_tree.api.node.open.preview()* + Open file with |'bufhidden'| set to `delete`. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + • {opts} (`table?`) optional + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. + • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + + *nvim_tree.api.node.open.preview_no_picker()* +open.preview_no_picker({node}, {opts}) + Open file with |'bufhidden'| set to `delete` without using the window + picker. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + • {opts} (`table?`) optional + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. + • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + + *nvim_tree.api.node.open.replace_tree_buffer()* +open.replace_tree_buffer({node}) + Open file in place: in the nvim-tree window. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) file + +open.tab({node}, {opts}) *nvim_tree.api.node.open.tab()* + Open file in a new tab. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + • {opts} (`table?`) optional + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. + • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + +open.tab_drop({node}) *nvim_tree.api.node.open.tab_drop()* + Switch to tab containing window with selected file if it exists. Open file + in new tab otherwise. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.node.open.toggle_group_empty()* +open.toggle_group_empty({node}, {opts}) + Toggle |nvim_tree.config.renderer| {group_empty} for a directory. Needs + {group_empty} set. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory + • {opts} (`table?`) optional + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. + • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + +open.vertical({node}, {opts}) *nvim_tree.api.node.open.vertical()* + Open file in a new vertical split. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) file + • {opts} (`table?`) optional + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. + • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + + *nvim_tree.api.node.open.vertical_no_picker()* +open.vertical_no_picker({node}, {opts}) + Open file in a new vertical split without using the window picker. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) file + • {opts} (`table?`) optional + • {quit_on_open}? (`boolean`, default: false) Quits the tree + when opening the file. + • {focus}? (`boolean`, default: false) Keep focus in the tree + when opening the file. + +run.cmd({node}) *nvim_tree.api.node.run.cmd()* + Enter |cmdline| with the full path of the node and the cursor at the start + of the line. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + +run.system({node}) *nvim_tree.api.node.run.system()* + Execute |nvim_tree.config.system_open|. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + +show_info_popup({node}) *nvim_tree.api.node.show_info_popup()* + Open a popup window showing: fullpath, size, accessed, modified, created. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + +============================================================================== +API: tree *nvim-tree-api-tree* + +change_root({path}) *nvim_tree.api.tree.change_root()* + Change the tree's root to a path. + + Parameters: ~ + • {path} (`string?`) absolute or relative path. + +change_root_to_node({node}) *nvim_tree.api.tree.change_root_to_node()* + Change the tree's root to a folder node or the parent of a file node. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + + *nvim_tree.api.tree.change_root_to_parent()* +change_root_to_parent({node}) + Change the tree's root to the parent of a node. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory or file + +close() *nvim_tree.api.tree.close()* + Close the tree, affecting all tabs as per |nvim_tree.config.tab.sync| + {close} + +close_in_all_tabs() *nvim_tree.api.tree.close_in_all_tabs()* + Close the tree in all tabs. + +close_in_this_tab() *nvim_tree.api.tree.close_in_this_tab()* + Close the tree in this tab only. + +collapse_all({opts}) *nvim_tree.api.tree.collapse_all()* + Collapse the tree. + + Parameters: ~ + • {opts} (`table?`) optional + • {keep_buffers}? (`boolean`, default: false) Do not collapse + nodes with open buffers. + +expand_all({node}, {opts}) *nvim_tree.api.tree.expand_all()* + Recursively expand all nodes under the tree root or specified folder. + + Parameters: ~ + • {node} (`nvim_tree.api.Node?`) directory + • {opts} (`table?`) optional + • {expand_until}? + (`fun(expansion_count: integer, node: Node): boolean`) + Return `true` if `node` should be expanded. + `expansion_count` is the total number of folders expanded. + +find_file({opts}) *nvim_tree.api.tree.find_file()* + Find and focus a file or folder in the tree. Finds current buffer unless + otherwise specified. + + Parameters: ~ + • {opts} (`table?`) optional + • {buf}? (`string|integer`) Absolute/relative path OR `bufnr` + to find. + • {open}? (`boolean`, default: false) Open the tree if + necessary. + • {current_window}? (`boolean`, default: false) Requires + {open}: open in the current window. + • {winid}? (`integer`) Open the tree in the specified + |window-ID|, overrides {current_window} + • {update_root}? (`boolean`, default: false) Update root after + find, see |nvim_tree.config.update_focused_file| + {update_root} + • {focus}? (`boolean`, default: false) Focus the tree window. + +focus() *nvim_tree.api.tree.focus()* + Focus the tree, opening it if necessary. Retained for compatibility, use + |nvim_tree.api.tree.open()| with no arguments instead. + +get_node_under_cursor() *nvim_tree.api.tree.get_node_under_cursor()* + Retrieve the currently focused node. + + Return: ~ + (`nvim_tree.api.Node?`) nil if tree is not visible. + +get_nodes() *nvim_tree.api.tree.get_nodes()* + Retrieve a hierarchical list of all the nodes. + + Return: ~ + (`nvim_tree.api.Node[]`) + +is_tree_buf({bufnr}) *nvim_tree.api.tree.is_tree_buf()* + Checks if a buffer is an nvim-tree. + + Parameters: ~ + • {bufnr} (`integer?`) 0 or nil for current buffer. + + Return: ~ + (`boolean`) + +is_visible({opts}) *nvim_tree.api.tree.is_visible()* + Checks if nvim-tree is visible on the current, specified or any tab. + + Parameters: ~ + • {opts} (`table?`) optional + • {tabpage}? (`integer`) |tab-ID| 0 or nil for current. + • {any_tabpage}? (`boolean`, default: false) Visible on any + tab. + + Return: ~ + (`boolean`) + +open({opts}) *nvim_tree.api.tree.open()* + Open the tree, focusing it if already open. + + Parameters: ~ + • {opts} (`table?`) optional + • {path}? (`string`) Root directory for the tree + • {current_window}? (`boolean`, default: false) Open the tree + in the current window + • {winid}? (`integer`) Open the tree in the specified + |window-ID|, overrides {current_window} + • {find_file}? (`boolean`, default: false) Find the current + buffer. + • {update_root}? (`boolean`, default: false) Update root + following {find_file}, see + |nvim_tree.config.update_focused_file| {update_root} + +reload() *nvim_tree.api.tree.reload()* + Refresh the tree. Does nothing if closed. + +resize({opts}) *nvim_tree.api.tree.resize()* + Resize the tree, persisting the new size. Resets to + |nvim_tree.config.view| {width} when no {opts} provided. + + Only one option is supported, priority order: {width}, {absolute}, + {relative}. + + {absolute} and {relative} do nothing when |nvim_tree.config.view| {width} + is a function. + + Parameters: ~ + • {opts} (`table?`) optional + • {width}? + (`nvim_tree.config.view.width.spec|nvim_tree.config.view.width`) + New |nvim_tree.config.view| {width} value. + • {absolute}? (`integer`) Set the width. + • {relative}? (`integer`) Increase or decrease the width. + +search_node() *nvim_tree.api.tree.search_node()* + Open the search dialogue. + +toggle({opts}) *nvim_tree.api.tree.toggle()* + Open or close the tree. + + Parameters: ~ + • {opts} (`table?`) optional + • {path}? (`string`) Root directory for the tree + • {current_window}? (`boolean`, default: false) Open the tree + in the current window + • {winid}? (`integer`) Open the tree in the specified + |window-ID|, overrides {current_window} + • {find_file}? (`boolean`, default: false) Find the current + buffer. + • {update_root}? (`boolean`, default: false) Update root + following {find_file}, see + |nvim_tree.config.update_focused_file| {update_root} + • {focus}? (`boolean`, default: true) Focus the tree when + opening. + +toggle_help() *nvim_tree.api.tree.toggle_help()* + Toggle help view. + +winid({opts}) *nvim_tree.api.tree.winid()* + Retrieve the window of the open tree. + + Parameters: ~ + • {opts} (`table?`) optional + • {tabpage}? (`integer`) |tab-ID| 0 or nil for current. + + Return: ~ + (`integer?`) |window-ID|, nil if tree is not visible. + + vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl: diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index b5a75d78db9..4d4dad7b1f3 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -1,3 +1,4 @@ +local api = require("nvim-tree.api") local log = require("nvim-tree.log") local view = require("nvim-tree.view") local utils = require("nvim-tree.utils") @@ -811,6 +812,8 @@ function M.setup(conf) vim.g.NvimTreeSetup = 1 vim.api.nvim_exec_autocmds("User", { pattern = "NvimTreeSetup" }) + + require("nvim-tree.api.impl.post")(api) end vim.g.NvimTreeRequired = 1 diff --git a/lua/nvim-tree/_meta/api/_git.lua b/lua/nvim-tree/_meta/api/_git.lua new file mode 100644 index 00000000000..0e9ea872d13 --- /dev/null +++ b/lua/nvim-tree/_meta/api/_git.lua @@ -0,0 +1,9 @@ +---@meta +local nvim_tree = { api = { git = {} } } + +--- +---Update the git status of the entire tree. +--- +function nvim_tree.api.git.reload() end + +return nvim_tree.api.git diff --git a/lua/nvim-tree/_meta/api/commands.lua b/lua/nvim-tree/_meta/api/commands.lua new file mode 100644 index 00000000000..e2d401d5be0 --- /dev/null +++ b/lua/nvim-tree/_meta/api/commands.lua @@ -0,0 +1,20 @@ +---@meta +local nvim_tree = { api = { commands = {} } } + +--- +---@class nvim_tree.api.commands.Command +---@inlinedoc +--- +---@field name string name of the `:NvimTree*` command +---@field command fun(args: vim.api.keyset.create_user_command.command_args) function that the command will execute +---@field opts vim.api.keyset.user_command [command-attributes] + +--- +---Retrieve all [nvim-tree-commands] +--- +---They have been created via [nvim_create_user_command()], see also [lua-guide-commands-create] +--- +---@return nvim_tree.api.commands.Command[] +function nvim_tree.api.commands.get() end + +return nvim_tree.api.commands diff --git a/lua/nvim-tree/_meta/api/deprecated.lua b/lua/nvim-tree/_meta/api/deprecated.lua new file mode 100644 index 00000000000..fdd4b88e85a --- /dev/null +++ b/lua/nvim-tree/_meta/api/deprecated.lua @@ -0,0 +1,33 @@ +---@meta +-- Deprecated top level API modules. +-- Remember to add mappings in legacy.lua `api_map` + +local nvim_tree = { api = {} } + +nvim_tree.api.config = {} + +nvim_tree.api.config.mappings = {} + +---@deprecated use `nvim_tree.api.map.keymap.current()` +function nvim_tree.api.config.mappings.get_keymap() end + +---@deprecated use `nvim_tree.api.map.keymap.default()` +function nvim_tree.api.config.mappings.get_keymap_default() end + +---@deprecated use `nvim_tree.api.map.on_attach.default()` +function nvim_tree.api.config.mappings.default_on_attach(bufnr) end + +nvim_tree.api.live_filter = {} + +---@deprecated use `nvim_tree.api.filter.live.start()` +function nvim_tree.api.live_filter.start() end + +---@deprecated use `nvim_tree.api.filter.live.clear()` +function nvim_tree.api.live_filter.clear() end + +nvim_tree.api.diagnostics = {} + +---@deprecated use `nvim_tree.api.health.hi_test()` +function nvim_tree.api.diagnostics.hi_test() end + +return nvim_tree.api diff --git a/lua/nvim-tree/_meta/api/events.lua b/lua/nvim-tree/_meta/api/events.lua new file mode 100644 index 00000000000..7e79e1c2c65 --- /dev/null +++ b/lua/nvim-tree/_meta/api/events.lua @@ -0,0 +1,11 @@ +---@meta +local nvim_tree = { api = { events = {} } } + +--- +---Register a handler for an event, see [nvim-tree-events]. +--- +---@param event_type string [nvim_tree_events_kind] +---@param callback fun(payload: table?) +function nvim_tree.api.events.subscribe(event_type, callback) end + +return nvim_tree.api.events diff --git a/lua/nvim-tree/_meta/api/filter.lua b/lua/nvim-tree/_meta/api/filter.lua new file mode 100644 index 00000000000..93b187a64cb --- /dev/null +++ b/lua/nvim-tree/_meta/api/filter.lua @@ -0,0 +1,65 @@ +---@meta +local nvim_tree = { api = { filter = {} } } + +--- +---Toggle [nvim_tree.config.filters] {enable} which applies to ALL filters. +--- +function nvim_tree.api.filter.toggle() end + +nvim_tree.api.filter.live = {} + +--- +---Enter live filter mode. Opens an input window with [filetype] `NvimTreeFilter` +--- +function nvim_tree.api.filter.live.start() end + +--- +---Exit live filter mode. +--- +function nvim_tree.api.filter.live.clear() end + +nvim_tree.api.filter.git = {} + +nvim_tree.api.filter.git.clean = {} + +--- +---Toggle [nvim_tree.config.filters] {git_clean} filter. +--- +function nvim_tree.api.filter.git.clean.toggle() end + +nvim_tree.api.filter.git.ignored = {} + +--- +---Toggle [nvim_tree.config.filters] {git_ignored} filter. +--- +function nvim_tree.api.filter.git.ignored.toggle() end + +nvim_tree.api.filter.dotfiles = {} + +--- +---Toggle [nvim_tree.config.filters] {dotfiles} filter. +--- +function nvim_tree.api.filter.dotfiles.toggle() end + +nvim_tree.api.filter.no_buffer = {} + +--- +---Toggle [nvim_tree.config.filters] {no_buffer} filter. +--- +function nvim_tree.api.filter.no_buffer.toggle() end + +nvim_tree.api.filter.no_bookmark = {} + +--- +---Toggle [nvim_tree.config.filters] {no_bookmark} filter. +--- +function nvim_tree.api.filter.no_bookmark.toggle() end + +nvim_tree.api.filter.custom = {} + +--- +---Toggle [nvim_tree.config.filters] {custom} filter. +--- +function nvim_tree.api.filter.custom.toggle() end + +return nvim_tree.api.filter diff --git a/lua/nvim-tree/_meta/api/fs.lua b/lua/nvim-tree/_meta/api/fs.lua new file mode 100644 index 00000000000..2ef16644823 --- /dev/null +++ b/lua/nvim-tree/_meta/api/fs.lua @@ -0,0 +1,114 @@ +---@meta +local nvim_tree = { api = { fs = {} } } + +--- +---Clear the nvim-tree clipboard. +--- +function nvim_tree.api.fs.clear_clipboard() end + +nvim_tree.api.fs.copy = {} + +--- +---Copy the absolute path to the system clipboard. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.copy.absolute_path(node) end + +--- +---Copy the name with extension omitted to the system clipboard. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.copy.basename(node) end + +--- +---Copy the name to the system clipboard. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.copy.filename(node) end + +--- +---Copy to the nvim-tree clipboard. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.copy.node(node) end + +--- +---Copy the path relative to the tree root to the system clipboard. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.copy.relative_path(node) end + +--- +---Prompt to create a file or directory. +--- +---When {node} is a file it will be created in the parent directory. +--- +---Use a trailing `"/"` to create a directory e.g. `"foo/"` +--- +---Multiple directories/files may be created e.g. `"foo/bar/baz"` +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.create(node) end + +--- +---Cut to the nvim-tree clipboard. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.cut(node) end + +--- +---Paste from the nvim-tree clipboard. +--- +---If {node} is a file it will pasted in the parent directory. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.paste(node) end + +--- +---Print the contents of the nvim-tree clipboard. +--- +function nvim_tree.api.fs.print_clipboard() end + +--- +---Delete from the file system. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.remove(node) end + +--- +---Prompt to rename by name. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.rename(node) end + +--- +---Prompt to rename by name with extension omitted. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.rename_basename(node) end + +--- +---Prompt to rename by absolute path. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.rename_full(node) end + +--- +---Prompt to rename. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.rename_node(node) end + +--- +---Prompt to rename by absolute path with name omitted. +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.rename_sub(node) end + +--- +---Trash as per |nvim_tree.config.trash| +--- +---@param node? nvim_tree.api.Node +function nvim_tree.api.fs.trash(node) end + +return nvim_tree.api.fs diff --git a/lua/nvim-tree/_meta/api/health.lua b/lua/nvim-tree/_meta/api/health.lua new file mode 100644 index 00000000000..088ae5076cd --- /dev/null +++ b/lua/nvim-tree/_meta/api/health.lua @@ -0,0 +1,11 @@ +---@meta +local nvim_tree = { api = { health = {} } } + +--- +---Open a new buffer displaying all nvim-tree highlight groups, their link chain and concrete definition. +--- +---Similar to `:so $VIMRUNTIME/syntax/hitest.vim` as per |:highlight| +--- +function nvim_tree.api.health.hi_test() end + +return nvim_tree.api.health diff --git a/lua/nvim-tree/_meta/api/map.lua b/lua/nvim-tree/_meta/api/map.lua new file mode 100644 index 00000000000..8273183eed7 --- /dev/null +++ b/lua/nvim-tree/_meta/api/map.lua @@ -0,0 +1,26 @@ +---@meta +local nvim_tree = { api = { map = {} } } + +nvim_tree.api.map.keymap = {} + +--- +---Retrieve all buffer local mappings for nvim-tree. These are the mappings that are applied by [nvim_tree.config] {on_attach}, which may include default mappings. +--- +---@return vim.api.keyset.get_keymap[] +function nvim_tree.api.map.keymap.current() end + +--- +--- Retrieves the buffer local mappings for nvim-tree that are applied by [nvim_tree.api.map.on_attach.default()] +--- +---@return vim.api.keyset.get_keymap[] +function nvim_tree.api.map.keymap.default() end + +nvim_tree.api.map.on_attach = {} + +--- +---Apply all [nvim-tree-mappings-default]. Call from your [nvim_tree.config] {on_attach}. +--- +---@param bufnr integer use the `bufnr` passed to {on_attach} +function nvim_tree.api.map.on_attach.default(bufnr) end + +return nvim_tree.api.map diff --git a/lua/nvim-tree/_meta/api/marks.lua b/lua/nvim-tree/_meta/api/marks.lua new file mode 100644 index 00000000000..332ff304c99 --- /dev/null +++ b/lua/nvim-tree/_meta/api/marks.lua @@ -0,0 +1,62 @@ +---@meta +local nvim_tree = { api = { marks = {} } } + +--- +---Return the node if it is marked. +--- +---@return nvim_tree.api.Node? +function nvim_tree.api.marks.get() end + +--- +---Retrieve all marked nodes. +--- +---@return nvim_tree.api.Node[] +function nvim_tree.api.marks.list() end + +--- +---Toggle mark. +--- +---@param node? nvim_tree.api.Node file or directory +function nvim_tree.api.marks.toggle(node) end + +--- +---Clear all marks. +--- +function nvim_tree.api.marks.clear() end + +nvim_tree.api.marks.bulk = {} + +--- +---Delete all marked, prompting if [nvim_tree.config.ui.confirm] {remove} +--- +function nvim_tree.api.marks.bulk.delete() end + +--- +---Delete all marked, prompting if [nvim_tree.config.ui.confirm] {trash} +--- +function nvim_tree.api.marks.bulk.trash() end + +--- +---Prompts for a directory to move all marked nodes into. +--- +function nvim_tree.api.marks.bulk.move() end + +nvim_tree.api.marks.navigate = {} + +--- +---Navigate to the next marked node, wraps. +--- +function nvim_tree.api.marks.navigate.next() end + +--- +---Navigate to the previous marked node, wraps. +--- +function nvim_tree.api.marks.navigate.prev() end + +--- +---Prompts for selection of a marked node, sorted by absolute paths. +---A folder will be focused, a file will be opened. +--- +function nvim_tree.api.marks.navigate.select() end + +return nvim_tree.api.marks diff --git a/lua/nvim-tree/_meta/api/node.lua b/lua/nvim-tree/_meta/api/node.lua new file mode 100644 index 00000000000..e6652bebc1b --- /dev/null +++ b/lua/nvim-tree/_meta/api/node.lua @@ -0,0 +1,294 @@ +---@meta +local nvim_tree = { api = { node = {} } } + +nvim_tree.api.node.open = {} + +--- +---@class nvim_tree.api.node.open.Opts +---@inlinedoc +--- +---Quits the tree when opening the file. +---(default: false) +---@field quit_on_open? boolean +--- +---Keep focus in the tree when opening the file. +---(default: false) +---@field focus? boolean + + +--- +---- file: open as per [nvim_tree.config.actions.open_file] +---- directory: expand or collapse +---- root: change directory up +--- +---@param node? nvim_tree.api.Node directory or file +---@param opts? nvim_tree.api.node.open.Opts optional +function nvim_tree.api.node.open.edit(node, opts) end + +--- +---Open file in a new horizontal split. +--- +---@param node? nvim_tree.api.Node file +---@param opts? nvim_tree.api.node.open.Opts optional +function nvim_tree.api.node.open.horizontal(node, opts) end + +--- +---Open file in a new horizontal split without using the window picker. +--- +---@param node? nvim_tree.api.Node file +---@param opts? nvim_tree.api.node.open.Opts optional +function nvim_tree.api.node.open.horizontal_no_picker(node, opts) end + +--- +---Open file without using the window picker. +--- +---@param node? nvim_tree.api.Node file +---@param opts? nvim_tree.api.node.open.Opts optional +function nvim_tree.api.node.open.no_window_picker(node, opts) end + +--- +---Open file with ['bufhidden'] set to `delete`. +--- +---@param node? nvim_tree.api.Node directory or file +---@param opts? nvim_tree.api.node.open.Opts optional +function nvim_tree.api.node.open.preview(node, opts) end + +--- +---Open file with ['bufhidden'] set to `delete` without using the window picker. +--- +---@param node? nvim_tree.api.Node directory or file +---@param opts? nvim_tree.api.node.open.Opts optional +function nvim_tree.api.node.open.preview_no_picker(node, opts) end + +--- +---Open file in place: in the nvim-tree window. +--- +---@param node? nvim_tree.api.Node file +function nvim_tree.api.node.open.replace_tree_buffer(node) end + +--- +---Open file in a new tab. +--- +---@param node? nvim_tree.api.Node directory or file +---@param opts? nvim_tree.api.node.open.Opts optional +function nvim_tree.api.node.open.tab(node, opts) end + +--- +---Switch to tab containing window with selected file if it exists. Open file in new tab otherwise. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.open.tab_drop(node) end + +--- +---Toggle [nvim_tree.config.renderer] {group_empty} for a directory. Needs {group_empty} set. +--- +---@param node? nvim_tree.api.Node directory +---@param opts? nvim_tree.api.node.open.Opts optional +function nvim_tree.api.node.open.toggle_group_empty(node, opts) end + +--- +---Open file in a new vertical split. +--- +---@param node? nvim_tree.api.Node file +---@param opts? nvim_tree.api.node.open.Opts optional +function nvim_tree.api.node.open.vertical(node, opts) end + +--- +---Open file in a new vertical split without using the window picker. +--- +---@param node? nvim_tree.api.Node file +---@param opts? nvim_tree.api.node.open.Opts optional +function nvim_tree.api.node.open.vertical_no_picker(node, opts) end + +--- +---@class nvim_tree.api.node.buffer.RemoveOpts +---@inlinedoc +--- +---Proceed even if the buffer is modified. +---(default: false) +---@field force? boolean + + +nvim_tree.api.node.buffer = {} + +--- +---Deletes node's related buffer, if one exists. Executes [:bdelete] or [:bdelete]! +--- +---@param node? nvim_tree.api.Node file +---@param opts? nvim_tree.api.node.buffer.RemoveOpts +function nvim_tree.api.node.buffer.delete(node, opts) end + +--- +---Wipes node's related buffer, if one exists. Executes [:bwipe] or [:bwipe]! +--- +---@param node? nvim_tree.api.Node file +---@param opts? nvim_tree.api.node.buffer.RemoveOpts optional +function nvim_tree.api.node.buffer.wipe(node, opts) end + +--- +---Collapse the tree under a directory or a file's parent directory. +--- +---@param node? nvim_tree.api.Node directory or file +---@param opts? nvim_tree.api.node.collapse.Opts optional +function nvim_tree.api.node.collapse(node, opts) end + +---@class nvim_tree.api.node.collapse.Opts +---@inlinedoc +--- +---Do not collapse nodes with open buffers. +---(default: false) +---@field keep_buffers? boolean + +--- +---Recursively expand all nodes under a directory or a file's parent directory. +--- +---@param node? nvim_tree.api.Node directory or file +---@param opts? nvim_tree.api.node.expand.Opts optional +function nvim_tree.api.node.expand(node, opts) end + +---@class nvim_tree.api.node.expand.Opts +---@inlinedoc +--- +---Return `true` if `node` should be expanded. `expansion_count` is the total number of folders expanded. +---@field expand_until? fun(expansion_count: integer, node: Node): boolean + + +nvim_tree.api.node.navigate = {} + +--- +---Navigate to the parent directory of the node. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.parent(node) end + +--- +---Navigate to the parent directory of the node, closing it. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.parent_close(node) end + +nvim_tree.api.node.navigate.diagnostics = {} + +--- +---Navigate to the next item showing diagnostic status. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.diagnostics.next(node) end + +--- +---Navigate to the next item showing diagnostic status, recursively. Needs [nvim_tree.config.diagnostics] {show_on_dirs} +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.diagnostics.next_recursive(node) end + +--- +---Navigate to the previous item showing diagnostic status. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.diagnostics.prev(node) end + +--- +---Navigate to the previous item showing diagnostic status, recursively. Needs [nvim_tree.config.diagnostics] {show_on_dirs} +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.diagnostics.prev_recursive(node) end + +nvim_tree.api.node.navigate.git = {} + +--- +---Navigate to the next item showing git status. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.git.next(node) end + +--- +---Navigate to the next item showing git status, recursively. Needs [nvim_tree.config.git] {show_on_dirs} +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.git.next_recursive(node) end + +--- +---Navigate to the next item showing git status, skipping `.gitignore` +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.git.next_skip_gitignored(node) end + +--- +---Navigate to the previous item showing git status. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.git.prev(node) end + +--- +---Navigate to the previous item showing git status, recursively. Needs [nvim_tree.config.git] {show_on_dirs} +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.git.prev_recursive(node) end + +--- +---Navigate to the previous item showing git status, skipping `.gitignore` +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.git.prev_skip_gitignored(node) end + +nvim_tree.api.node.navigate.opened = {} + +--- +---Navigate to the next [bufloaded()] file. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.opened.next(node) end + +--- +---Navigate to the previous [bufloaded()] file. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.opened.prev(node) end + +nvim_tree.api.node.navigate.sibling = {} + +--- +---Navigate to the first node in the current node's folder. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.sibling.first(node) end + +--- +---Navigate to the last node in the current node's folder. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.sibling.last(node) end + +--- +---Navigate to the next node in the current node's folder, wraps. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.sibling.next(node) end + +--- +---Navigate to the previous node in the current node's folder, wraps. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.navigate.sibling.prev(node) end + +nvim_tree.api.node.run = {} + +--- +---Enter [cmdline] with the full path of the node and the cursor at the start of the line. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.run.cmd(node) end + +--- +---Execute [nvim_tree.config.system_open]. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.run.system(node) end + +--- +---Open a popup window showing: fullpath, size, accessed, modified, created. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.node.show_info_popup(node) end + +return nvim_tree.api.node diff --git a/lua/nvim-tree/_meta/api/tree.lua b/lua/nvim-tree/_meta/api/tree.lua new file mode 100644 index 00000000000..db77950c1ec --- /dev/null +++ b/lua/nvim-tree/_meta/api/tree.lua @@ -0,0 +1,253 @@ +---@meta +local nvim_tree = { api = { tree = {} } } + +--- +---Open the tree, focusing it if already open. +--- +---@param opts? nvim_tree.api.tree.open.Opts optional +function nvim_tree.api.tree.open(opts) end + +---@class nvim_tree.api.tree.open.Opts +---@inlinedoc +--- +---Root directory for the tree +---@field path? string +--- +---Open the tree in the current window +---(default: false) +---@field current_window? boolean +--- +---Open the tree in the specified [window-ID], overrides {current_window} +---@field winid? integer +--- +---Find the current buffer. +---(default: false) +---@field find_file? boolean +--- +---Update root following {find_file}, see [nvim_tree.config.update_focused_file] {update_root} +---(default: false) +---@field update_root? boolean + +--- +---Open or close the tree. +--- +---@param opts? nvim_tree.api.tree.toggle.Opts optional +function nvim_tree.api.tree.toggle(opts) end + +---@class nvim_tree.api.tree.toggle.Opts +---@inlinedoc +--- +---Root directory for the tree +---@field path? string +--- +---Open the tree in the current window +---(default: false) +---@field current_window? boolean +--- +---Open the tree in the specified [window-ID], overrides {current_window} +---@field winid? integer +--- +---Find the current buffer. +---(default: false) +---@field find_file? boolean +--- +---Update root following {find_file}, see [nvim_tree.config.update_focused_file] {update_root} +---(default: false) +---@field update_root? boolean +--- +---Focus the tree when opening. +---(default: true) +---@field focus? boolean + +--- +---Close the tree, affecting all tabs as per [nvim_tree.config.tab.sync] {close} +--- +function nvim_tree.api.tree.close() end + +--- +---Close the tree in this tab only. +--- +function nvim_tree.api.tree.close_in_this_tab() end + +--- +---Close the tree in all tabs. +--- +function nvim_tree.api.tree.close_in_all_tabs() end + +--- +---Focus the tree, opening it if necessary. Retained for compatibility, use [nvim_tree.api.tree.open()] with no arguments instead. +--- +function nvim_tree.api.tree.focus() end + +--- +---Refresh the tree. Does nothing if closed. +--- +function nvim_tree.api.tree.reload() end + +--- +---Resize the tree, persisting the new size. Resets to [nvim_tree.config.view] {width} when no {opts} provided. +--- +---Only one option is supported, priority order: {width}, {absolute}, {relative}. +--- +---{absolute} and {relative} do nothing when [nvim_tree.config.view] {width} is a function. +--- +---@param opts? nvim_tree.api.tree.resize.Opts optional +function nvim_tree.api.tree.resize(opts) end + +---@class nvim_tree.api.tree.resize.Opts +---@inlinedoc +--- +---New [nvim_tree.config.view] {width} value. +---@field width? nvim_tree.config.view.width.spec|nvim_tree.config.view.width +--- +---Set the width. +---@field absolute? integer +--- +---Increase or decrease the width. +---@field relative? integer + +--- +---Change the tree's root to a path. +--- +---@param path? string absolute or relative path. +function nvim_tree.api.tree.change_root(path) end + +--- +---Change the tree's root to a folder node or the parent of a file node. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.tree.change_root_to_node(node) end + +--- +---Change the tree's root to the parent of a node. +--- +---@param node? nvim_tree.api.Node directory or file +function nvim_tree.api.tree.change_root_to_parent(node) end + +--- +---Retrieve the currently focused node. +--- +---@return nvim_tree.api.Node? nil if tree is not visible. +function nvim_tree.api.tree.get_node_under_cursor() end + +--- +---Retrieve a hierarchical list of all the nodes. +--- +---@return nvim_tree.api.Node[] +function nvim_tree.api.tree.get_nodes() end + +--- +---Find and focus a file or folder in the tree. Finds current buffer unless otherwise specified. +--- +---@param opts? nvim_tree.api.tree.find_file.Opts optional +function nvim_tree.api.tree.find_file(opts) end + +---@class nvim_tree.api.tree.find_file.Opts +---@inlinedoc +--- +---Absolute/relative path OR `bufnr` to find. +---@field buf? string|integer +--- +---Open the tree if necessary. +---(default: false) +---@field open? boolean +--- +---Requires {open}: open in the current window. +---(default: false) +---@field current_window? boolean +--- +---Open the tree in the specified [window-ID], overrides {current_window} +---@field winid? integer +--- +---Update root after find, see [nvim_tree.config.update_focused_file] {update_root} +---(default: false) +---@field update_root? boolean +--- +---Focus the tree window. +---(default: false) +---@field focus? boolean + +--- +---Open the search dialogue. +--- +function nvim_tree.api.tree.search_node() end + +--- +---Collapse the tree. +--- +---@param opts? nvim_tree.api.node.collapse.Opts optional +function nvim_tree.api.tree.collapse_all(opts) end + +--- +---Recursively expand all nodes under the tree root or specified folder. +--- +---@param node? nvim_tree.api.Node directory +---@param opts? nvim_tree.api.node.expand.Opts optional +function nvim_tree.api.tree.expand_all(node, opts) end + +--- +---Toggle help view. +--- +function nvim_tree.api.tree.toggle_help() end + +--- +---Checks if a buffer is an nvim-tree. +--- +---@param bufnr? integer 0 or nil for current buffer. +--- +---@return boolean +function nvim_tree.api.tree.is_tree_buf(bufnr) end + +--- +---Checks if nvim-tree is visible on the current, specified or any tab. +--- +---@param opts? nvim_tree.api.tree.is_visible.Opts optional +---@return boolean +function nvim_tree.api.tree.is_visible(opts) end + +---@class nvim_tree.api.tree.is_visible.Opts +---@inlinedoc +--- +--- [tab-ID] 0 or nil for current. +---@field tabpage? integer +--- +---Visible on any tab. +---(default: false) +---@field any_tabpage? boolean + +--- +---Retrieve the window of the open tree. +--- +---@param opts? nvim_tree.api.tree.winid.Opts optional +---@return integer? [window-ID], nil if tree is not visible. +function nvim_tree.api.tree.winid(opts) end + +---@class nvim_tree.api.tree.winid.Opts +---@inlinedoc +--- +---[tab-ID] 0 or nil for current. +---@field tabpage? integer + + +---@deprecated use `nvim_tree.api.filter.toggle()` +function nvim_tree.api.tree.toggle_enable_filters() end + +---@deprecated use `nvim_tree.api.filter.git.ignored.toggle()` +function nvim_tree.api.tree.toggle_gitignore_filter() end + +---@deprecated use `nvim_tree.api.filter.git.clean.toggle()` +function nvim_tree.api.tree.toggle_git_clean_filter() end + +---@deprecated use `nvim_tree.api.filter.no_buffer.toggle()` +function nvim_tree.api.tree.toggle_no_buffer_filter() end + +---@deprecated use `nvim_tree.api.filter.custom.toggle()` +function nvim_tree.api.tree.toggle_custom_filter() end + +---@deprecated use `nvim_tree.api.filter.dotfiles.toggle()` +function nvim_tree.api.tree.toggle_hidden_filter() end + +---@deprecated use `nvim_tree.api.filter.no_bookmark.toggle()` +function nvim_tree.api.tree.toggle_no_bookmark_filter() end + +return nvim_tree.api.tree diff --git a/lua/nvim-tree/_meta/api_decorator.lua b/lua/nvim-tree/_meta/api_decorator.lua index d85fe02fff0..4acca3a9acf 100644 --- a/lua/nvim-tree/_meta/api_decorator.lua +++ b/lua/nvim-tree/_meta/api_decorator.lua @@ -12,6 +12,11 @@ local nvim_tree = { api = { decorator = {} } } ---Names of builtin decorators or your decorator classes. Builtins are ordered lowest to highest priority. ---@alias nvim_tree.api.decorator.Name "Git" | "Opened" | "Hidden" | "Modified" | "Bookmarks" | "Diagnostics" | "Copied" | "Cut" | nvim_tree.api.decorator.UserDecorator +---A string for rendering, with optional highlight groups to apply to it +---@class (exact) nvim_tree.api.HighlightedString +---@field str string +---@field hl string[] + ---Custom decorator, see :help nvim-tree-decorators --- ---@class (exact) nvim_tree.api.decorator.UserDecorator diff --git a/lua/nvim-tree/_meta/api.lua b/lua/nvim-tree/_meta/classes.lua similarity index 55% rename from lua/nvim-tree/_meta/api.lua rename to lua/nvim-tree/_meta/classes.lua index d6847940781..859c457a8e7 100644 --- a/lua/nvim-tree/_meta/api.lua +++ b/lua/nvim-tree/_meta/classes.lua @@ -1,51 +1,43 @@ ---@meta error("Cannot require a meta file") --- --- Nodes --- - ----Base Node, Abstract ----@class (exact) nvim_tree.api.Node ----@field type "file" | "directory" | "link" uv.fs_stat.result.type ----@field absolute_path string ----@field executable boolean ----@field fs_stat uv.fs_stat.result? ----@field git_status GitNodeStatus? ----@field hidden boolean ----@field name string ----@field parent nvim_tree.api.DirectoryNode? ----@field diag_severity lsp.DiagnosticSeverity? +-- These node subclasses are not ready for public exposure as they are: +-- - not classic classes +-- - only used in a few locations: api.tree.get_nodes and UserDecorator + +--- ---File +--- ---@class (exact) nvim_tree.api.FileNode: nvim_tree.api.Node ---@field extension string +--- ---Directory +--- ---@class (exact) nvim_tree.api.DirectoryNode: nvim_tree.api.Node ---@field has_children boolean ---@field nodes nvim_tree.api.Node[] ---@field open boolean +--- ---Root Directory +--- ---@class (exact) nvim_tree.api.RootNode: nvim_tree.api.DirectoryNode +--- ---Link mixin +--- ---@class (exact) nvim_tree.api.LinkNode ---@field link_to string ---@field fs_stat_target uv.fs_stat.result +--- ---File Link +--- ---@class (exact) nvim_tree.api.FileLinkNode: nvim_tree.api.FileNode, nvim_tree.api.LinkNode +--- ---DirectoryLink +--- ---@class (exact) nvim_tree.api.DirectoryLinkNode: nvim_tree.api.DirectoryNode, nvim_tree.api.LinkNode - --- --- Various Types --- - ----A string for rendering, with optional highlight groups to apply to it ----@class (exact) nvim_tree.api.HighlightedString ----@field str string ----@field hl string[] diff --git a/lua/nvim-tree/_meta/config/actions.lua b/lua/nvim-tree/_meta/config/actions.lua index 2228c15a87e..316ec3a47b1 100644 --- a/lua/nvim-tree/_meta/config/actions.lua +++ b/lua/nvim-tree/_meta/config/actions.lua @@ -43,7 +43,7 @@ error("Cannot require a meta file") ----Configure [nvim-tree-api.tree.expand_all()] and [nvim-tree-api.node.expand()] +---Configure [nvim_tree.api.tree.expand_all()] and [nvim_tree.api.node.expand()] ---@class nvim_tree.config.actions.expand_all --- ---Limit the number of folders being explored when expanding every folder. Avoids hanging Nvim when running this action on very large folders. diff --git a/lua/nvim-tree/_meta/config/filters.lua b/lua/nvim-tree/_meta/config/filters.lua index 37dc67b5840..746bc5f1a36 100644 --- a/lua/nvim-tree/_meta/config/filters.lua +++ b/lua/nvim-tree/_meta/config/filters.lua @@ -9,27 +9,27 @@ error("Cannot require a meta file") --- ---Filters can be set at startup or toggled live via API with default mappings. --- ----`I `{git_ignored}` `|nvim-tree-api.tree.toggle_gitignore_filter()| +---`I `{git_ignored}` `|nvim_tree.api.filter.git.ignored.toggle()| ---Ignore files based on `.gitignore`. Requires |nvim_tree.config.git| --- ----`H `{dotfiles}` `|nvim-tree-api.tree.toggle_hidden_filter()| +---`H `{dotfiles}` `|nvim_tree.api.filter.dotfiles.toggle()| ---Filter dotfiles: files/directories starting with a `.` --- ----`C `{git_clean}` `|nvim-tree-api.tree.toggle_git_clean_filter()| +---`C `{git_clean}` `|nvim_tree.api.filter.git.clean.toggle()| ---Filter files with no git status. `.gitignore` files will not be filtered when {git_ignored}, as they are effectively dirty. --- ----`B `{no_buffer}` `|nvim-tree-api.tree.toggle_no_buffer_filter()| +---`B `{no_buffer}` `|nvim_tree.api.filter.no_buffer.toggle()| ---Filter files that have no |buflisted()| buffer. For performance reasons buffer delete/wipe may not be immediately shown. A reload or filesystem event will always result in an update. --- ----`M `{no_bookmark}` `|nvim-tree-api.tree.toggle_no_bookmark_filter()| +---`M `{no_bookmark}` `|nvim_tree.api.filter.no_bookmark.toggle()| ---Filter files that are not bookmarked. Enabling this is not useful as there is no means yet to persist bookmarks. --- ----`U `{custom}` `|nvim-tree-api.tree.toggle_custom_filter()| +---`U `{custom}` `|nvim_tree.api.filter.custom.toggle()| ---Disable specific file/directory names via: ---- a list of backslash escaped |vim.regex| strings e.g. `"^\\.git""` ---- a function passed the absolute path of the directory. --- ----All filters including live filter may be disabled via {enable} and toggled with |nvim-tree-api.tree.toggle_enable_filters()| +---All filters including live filter may be disabled via {enable} and toggled with |nvim_tree.api.filter.toggle()| --- ---Files/directories may be {exclude}d from filtering: they will always be shown, overriding {git_ignored}, {dotfiles} and {custom}. ---@class nvim_tree.config.filters diff --git a/lua/nvim-tree/actions/node/buffer.lua b/lua/nvim-tree/actions/node/buffer.lua index 425fcfa4ba6..7e6610f84af 100644 --- a/lua/nvim-tree/actions/node/buffer.lua +++ b/lua/nvim-tree/actions/node/buffer.lua @@ -4,15 +4,13 @@ local notify = require("nvim-tree.notify") local M = {} ---@param node Node ----@param opts ApiNodeDeleteWipeBufferOpts|nil ----@return nil +---@param opts? nvim_tree.api.node.buffer.RemoveOpts function M.delete(node, opts) M.delete_buffer("delete", node.absolute_path, opts) end ---@param node Node ----@param opts ApiNodeDeleteWipeBufferOpts|nil ----@return nil +---@param opts? nvim_tree.api.node.buffer.RemoveOpts function M.wipe(node, opts) M.delete_buffer("wipe", node.absolute_path, opts) end @@ -21,8 +19,7 @@ end ---@param mode ApiNodeDeleteWipeBufferMode ---@param filename string ----@param opts ApiNodeDeleteWipeBufferOpts|nil ----@return nil +---@param opts? nvim_tree.api.node.buffer.RemoveOpts function M.delete_buffer(mode, filename, opts) if type(mode) ~= "string" then mode = "delete" diff --git a/lua/nvim-tree/actions/tree/collapse.lua b/lua/nvim-tree/actions/tree/collapse.lua index 51a15f3d464..b0611e21789 100644 --- a/lua/nvim-tree/actions/tree/collapse.lua +++ b/lua/nvim-tree/actions/tree/collapse.lua @@ -25,8 +25,8 @@ local function buf_match() end ---Collapse a node, root if nil ----@param node Node? ----@param opts ApiCollapseOpts +---@param node? Node +---@param opts nvim_tree.api.node.collapse.Opts local function collapse(node, opts) local explorer = core.get_explorer() if not explorer then @@ -60,7 +60,7 @@ local function collapse(node, opts) end ----@param opts ApiCollapseOpts|boolean|nil legacy -> opts.keep_buffers +---@param opts? nvim_tree.api.node.collapse.Opts|boolean legacy -> opts.keep_buffers function M.all(opts) -- legacy arguments if type(opts) == "boolean" then @@ -72,8 +72,8 @@ function M.all(opts) collapse(nil, opts or {}) end ----@param node Node ----@param opts ApiCollapseOpts? +---@param node? Node +---@param opts? nvim_tree.api.node.collapse.Opts function M.node(node, opts) collapse(node, opts or {}) end diff --git a/lua/nvim-tree/actions/tree/find-file.lua b/lua/nvim-tree/actions/tree/find-file.lua index 8a05bf6db45..0290ce2e17f 100644 --- a/lua/nvim-tree/actions/tree/find-file.lua +++ b/lua/nvim-tree/actions/tree/find-file.lua @@ -6,7 +6,7 @@ local finders_find_file = require("nvim-tree.actions.finders.find-file") local M = {} --- Find file or buffer ----@param opts ApiTreeFindFileOpts|nil|boolean legacy -> opts.buf +---@param opts? nvim_tree.api.tree.find_file.Opts|boolean legacy -> opts.buf function M.fn(opts) -- legacy arguments if type(opts) == "string" then diff --git a/lua/nvim-tree/actions/tree/modifiers/expand.lua b/lua/nvim-tree/actions/tree/modifiers/expand.lua new file mode 100644 index 00000000000..14409011ef3 --- /dev/null +++ b/lua/nvim-tree/actions/tree/modifiers/expand.lua @@ -0,0 +1,165 @@ +local core = require("nvim-tree.core") +local Iterator = require("nvim-tree.iterators.node-iterator") +local notify = require("nvim-tree.notify") + +local FileNode = require("nvim-tree.node.file") +local DirectoryNode = require("nvim-tree.node.directory") + +local M = {} + +---@param list string[] +---@return table +local function to_lookup_table(list) + local table = {} + for _, element in ipairs(list) do + table[element] = true + end + + return table +end + +---@param node DirectoryNode +local function expand(node) + node = node:last_group_node() + node.open = true + if #node.nodes == 0 then + core.get_explorer():expand_dir_node(node) + end +end + +---@param should_descend fun(expansion_count: integer, node: Node): boolean +---@return fun(expansion_count: integer, node: Node): boolean +local function limit_folder_discovery(should_descend) + return function(expansion_count, node) + local should_halt = expansion_count >= M.MAX_FOLDER_DISCOVERY + if should_halt then + notify.warn("expansion iteration was halted after " .. M.MAX_FOLDER_DISCOVERY .. " discovered folders") + return false + end + + return should_descend(expansion_count, node) + end +end + +---@param _ integer expansion_count +---@param node Node +---@return boolean +local function descend_until_empty(_, node) + local dir = node:as(DirectoryNode) + if not dir then + return false + end + + local should_exclude = M.EXCLUDE[dir.name] + return not should_exclude +end + +---@param expansion_count integer +---@param node Node +---@param should_descend fun(expansion_count: integer, node: Node): boolean +---@return boolean +local function should_expand(expansion_count, node, should_descend) + local dir = node:as(DirectoryNode) + if not dir then + return false + end + + if not dir.open and should_descend(expansion_count, node) then + if #node.nodes == 0 then + core.get_explorer():expand_dir_node(dir) -- populate node.group_next + end + + if dir.group_next then + local expand_next = should_expand(expansion_count, dir.group_next, should_descend) + if expand_next then + dir.open = true + end + return expand_next + else + return true + end + end + return false +end + + +---@param should_descend fun(expansion_count: integer, node: Node): boolean +---@return fun(node): any +local function gen_iterator(should_descend) + local expansion_count = 0 + + return function(parent) + if parent.parent and parent.nodes and not parent.open then + expansion_count = expansion_count + 1 + expand(parent) + end + + Iterator.builder(parent.nodes) + :hidden() + :applier(function(node) + if should_expand(expansion_count, node, should_descend) then + expansion_count = expansion_count + 1 + node = node:as(DirectoryNode) + if node then + expand(node) + end + end + end) + :recursor(function(node) + if not should_descend(expansion_count, node) then + return nil + end + + if node.group_next then + return { node.group_next } + end + + if node.open and node.nodes then + return node.nodes + end + + return nil + end) + :iterate() + end +end + +---@param node? Node +---@param expand_opts? nvim_tree.api.node.expand.Opts +local function expand_node(node, expand_opts) + if not node then + return + end + local descend_until = limit_folder_discovery((expand_opts and expand_opts.expand_until) or descend_until_empty) + gen_iterator(descend_until)(node) + + local explorer = core.get_explorer() + if explorer then + explorer.renderer:draw() + end +end + +---Expand the directory node or the root +---@param node Node +---@param expand_opts nvim_tree.api.node.expand.Opts? +function M.all(node, expand_opts) + expand_node(node and node:as(DirectoryNode) or core.get_explorer(), expand_opts) +end + +---Expand the directory node or parent node +---@param node? Node +---@param expand_opts? nvim_tree.api.node.expand.Opts +function M.node(node, expand_opts) + if not node then + return + end + + expand_node(node:is(FileNode) and node.parent or node:as(DirectoryNode), expand_opts) +end + +function M.setup(opts) + M.MAX_FOLDER_DISCOVERY = opts.actions.expand_all.max_folder_discovery + M.EXCLUDE = to_lookup_table(opts.actions.expand_all.exclude) +end + +return M diff --git a/lua/nvim-tree/actions/tree/open.lua b/lua/nvim-tree/actions/tree/open.lua index ff2da837b87..8c559d8cb54 100644 --- a/lua/nvim-tree/actions/tree/open.lua +++ b/lua/nvim-tree/actions/tree/open.lua @@ -5,7 +5,7 @@ local finders_find_file = require("nvim-tree.actions.finders.find-file") local M = {} ---Open the tree, focusing if already open. ----@param opts ApiTreeOpenOpts|nil|string legacy -> opts.path +---@param opts? nvim_tree.api.tree.open.Opts|string legacy -> opts.path function M.fn(opts) -- legacy arguments if type(opts) == "string" then diff --git a/lua/nvim-tree/actions/tree/resize.lua b/lua/nvim-tree/actions/tree/resize.lua index e8d4e950729..7498efdfcca 100644 --- a/lua/nvim-tree/actions/tree/resize.lua +++ b/lua/nvim-tree/actions/tree/resize.lua @@ -3,7 +3,7 @@ local view = require("nvim-tree.view") local M = {} ---Resize the tree, persisting the new size. ----@param opts ApiTreeResizeOpts|nil +---@param opts? nvim_tree.api.tree.resize.Opts function M.fn(opts) if opts == nil then -- reset to config values diff --git a/lua/nvim-tree/actions/tree/toggle.lua b/lua/nvim-tree/actions/tree/toggle.lua index 10aa978467e..cb9e557838a 100644 --- a/lua/nvim-tree/actions/tree/toggle.lua +++ b/lua/nvim-tree/actions/tree/toggle.lua @@ -5,10 +5,10 @@ local finders_find_file = require("nvim-tree.actions.finders.find-file") local M = {} ---Toggle the tree. ----@param opts ApiTreeToggleOpts|nil|boolean legacy -> opts.find_file ----@param no_focus string|nil legacy -> opts.focus ----@param cwd boolean|nil legacy -> opts.path ----@param bang boolean|nil legacy -> opts.update_root +---@param opts? nvim_tree.api.tree.toggle.Opts|boolean legacy -> opts.find_file +---@param no_focus? string legacy -> opts.focus +---@param cwd? boolean legacy -> opts.path +---@param bang? boolean legacy -> opts.update_root function M.fn(opts, no_focus, cwd, bang) -- legacy arguments if type(opts) == "boolean" then diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index 7bf316231fb..f1d533f6f5f 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -1,360 +1,105 @@ -local core = require("nvim-tree.core") -local view = require("nvim-tree.view") -local utils = require("nvim-tree.utils") -local actions = require("nvim-tree.actions") -local appearance_hi_test = require("nvim-tree.appearance.hi-test") -local events = require("nvim-tree.events") -local help = require("nvim-tree.help") -local keymap = require("nvim-tree.keymap") -local notify = require("nvim-tree.notify") - -local DirectoryNode = require("nvim-tree.node.directory") -local FileLinkNode = require("nvim-tree.node.file-link") -local RootNode = require("nvim-tree.node.root") -local UserDecorator = require("nvim-tree.renderer.decorator.user") - -local Api = { - tree = {}, - node = { - navigate = { - sibling = {}, - git = {}, - diagnostics = {}, - opened = {}, - }, - run = {}, - open = {}, - buffer = {}, - }, - events = {}, - marks = { - bulk = {}, - navigate = {}, - }, - fs = { - copy = {}, - }, - git = {}, - live_filter = {}, - config = { - mappings = {}, - }, - commands = {}, - diagnostics = {}, - decorator = {}, -} - ----Print error when setup not called. ----@param fn fun(...): any ----@return fun(...): any -local function wrap(fn) - return function(...) - if vim.g.NvimTreeSetup == 1 then - return fn(...) - else - notify.error("nvim-tree setup not called") - end - end -end - ----Invoke a method on the singleton explorer. ----Print error when setup not called. ----@param explorer_method string explorer method name ----@return fun(...): any -local function wrap_explorer(explorer_method) - return wrap(function(...) - local explorer = core.get_explorer() - if explorer then - return explorer[explorer_method](explorer, ...) - end - end) -end - ----Inject the node as the first argument if present otherwise do nothing. ----@param fn fun(node: Node, ...): any ----@return fun(node: Node?, ...): any -local function wrap_node(fn) - return function(node, ...) - node = node or wrap_explorer("get_node_at_cursor")() - if node then - return fn(node, ...) - end - end -end - ----Inject the node or nil as the first argument if absent. ----@param fn fun(node: Node?, ...): any ----@return fun(node: Node?, ...): any -local function wrap_node_or_nil(fn) - return function(node, ...) - node = node or wrap_explorer("get_node_at_cursor")() - return fn(node, ...) - end -end - ----Invoke a member's method on the singleton explorer. ----Print error when setup not called. ----@param explorer_member string explorer member name ----@param member_method string method name to invoke on member ----@param ... any passed to method ----@return fun(...): any -local function wrap_explorer_member_args(explorer_member, member_method, ...) - local method_args = ... - return wrap(function(...) - local explorer = core.get_explorer() - if explorer then - return explorer[explorer_member][member_method](explorer[explorer_member], method_args, ...) - end - end) -end - ----Invoke a member's method on the singleton explorer. ----Print error when setup not called. ----@param explorer_member string explorer member name ----@param member_method string method name to invoke on member ----@return fun(...): any -local function wrap_explorer_member(explorer_member, member_method) - return wrap(function(...) - local explorer = core.get_explorer() - if explorer then - return explorer[explorer_member][member_method](explorer[explorer_member], ...) - end - end) -end - ----@class ApiTreeOpenOpts ----@field path string|nil path ----@field current_window boolean|nil default false ----@field winid number|nil ----@field find_file boolean|nil default false ----@field update_root boolean|nil default false - -Api.tree.open = wrap(actions.tree.open.fn) -Api.tree.focus = Api.tree.open - ----@class ApiTreeToggleOpts ----@field path string|nil ----@field current_window boolean|nil default false ----@field winid number|nil ----@field find_file boolean|nil default false ----@field update_root boolean|nil default false ----@field focus boolean|nil default true - -Api.tree.toggle = wrap(actions.tree.toggle.fn) -Api.tree.close = wrap(view.close) -Api.tree.close_in_this_tab = wrap(view.close_this_tab_only) -Api.tree.close_in_all_tabs = wrap(view.close_all_tabs) -Api.tree.reload = wrap_explorer("reload_explorer") - ----@class ApiTreeResizeOpts ----@field width string|function|number|table|nil ----@field absolute number|nil ----@field relative number|nil - -Api.tree.resize = wrap(actions.tree.resize.fn) - -Api.tree.change_root = wrap(function(...) - require("nvim-tree").change_dir(...) -end) - -Api.tree.change_root_to_node = wrap_node(wrap_explorer("change_dir_to_node")) -Api.tree.change_root_to_parent = wrap_node(wrap_explorer("dir_up")) -Api.tree.get_node_under_cursor = wrap_explorer("get_node_at_cursor") -Api.tree.get_nodes = wrap_explorer("get_nodes") - ----@class ApiTreeFindFileOpts ----@field buf string|number|nil ----@field open boolean|nil default false ----@field current_window boolean|nil default false ----@field winid number|nil ----@field update_root boolean|nil default false ----@field focus boolean|nil default false - -Api.tree.find_file = wrap(actions.tree.find_file.fn) -Api.tree.search_node = wrap(actions.finders.search_node.fn) - ----@class ApiCollapseOpts ----@field keep_buffers boolean|nil default false - -Api.tree.collapse_all = wrap(actions.tree.collapse.all) - ----@class ApiTreeExpandOpts ----@field expand_until (fun(expansion_count: integer, node: Node): boolean)|nil - -Api.tree.expand_all = wrap_node(wrap_explorer("expand_all")) -Api.tree.toggle_enable_filters = wrap_explorer_member("filters", "toggle") -Api.tree.toggle_gitignore_filter = wrap_explorer_member_args("filters", "toggle", "git_ignored") -Api.tree.toggle_git_clean_filter = wrap_explorer_member_args("filters", "toggle", "git_clean") -Api.tree.toggle_no_buffer_filter = wrap_explorer_member_args("filters", "toggle", "no_buffer") -Api.tree.toggle_custom_filter = wrap_explorer_member_args("filters", "toggle", "custom") -Api.tree.toggle_hidden_filter = wrap_explorer_member_args("filters", "toggle", "dotfiles") -Api.tree.toggle_no_bookmark_filter = wrap_explorer_member_args("filters", "toggle", "no_bookmark") -Api.tree.toggle_help = wrap(help.toggle) -Api.tree.is_tree_buf = wrap(utils.is_nvim_tree_buf) - ----@class ApiTreeIsVisibleOpts ----@field tabpage number|nil ----@field any_tabpage boolean|nil default false - -Api.tree.is_visible = wrap(view.is_visible) - ----@class ApiTreeWinIdOpts ----@field tabpage number|nil default nil - -Api.tree.winid = wrap(view.winid) - -Api.fs.create = wrap_node_or_nil(actions.fs.create_file.fn) -Api.fs.remove = wrap_node(actions.fs.remove_file.fn) -Api.fs.trash = wrap_node(actions.fs.trash.fn) -Api.fs.rename_node = wrap_node(actions.fs.rename_file.fn(":t")) -Api.fs.rename = wrap_node(actions.fs.rename_file.fn(":t")) -Api.fs.rename_sub = wrap_node(actions.fs.rename_file.fn(":p:h")) -Api.fs.rename_basename = wrap_node(actions.fs.rename_file.fn(":t:r")) -Api.fs.rename_full = wrap_node(actions.fs.rename_file.fn(":p")) -Api.fs.cut = wrap_node(wrap_explorer_member("clipboard", "cut")) -Api.fs.paste = wrap_node(wrap_explorer_member("clipboard", "paste")) -Api.fs.clear_clipboard = wrap_explorer_member("clipboard", "clear_clipboard") -Api.fs.print_clipboard = wrap_explorer_member("clipboard", "print_clipboard") -Api.fs.copy.node = wrap_node(wrap_explorer_member("clipboard", "copy")) -Api.fs.copy.absolute_path = wrap_node(wrap_explorer_member("clipboard", "copy_absolute_path")) -Api.fs.copy.filename = wrap_node(wrap_explorer_member("clipboard", "copy_filename")) -Api.fs.copy.basename = wrap_node(wrap_explorer_member("clipboard", "copy_basename")) -Api.fs.copy.relative_path = wrap_node(wrap_explorer_member("clipboard", "copy_path")) +---@brief +---nvim-tree exposes a public API. This is non breaking, with additions made as necessary. --- ----@class NodeEditOpts ----@field quit_on_open boolean|nil default false ----@field focus boolean|nil default true - ----@param mode string ----@param node Node ----@param edit_opts NodeEditOpts? -local function edit(mode, node, edit_opts) - local file_link = node:as(FileLinkNode) - local path = file_link and file_link.link_to or node.absolute_path - local cur_tabpage = vim.api.nvim_get_current_tabpage() - - actions.node.open_file.fn(mode, path) - - edit_opts = edit_opts or {} - - local mode_unsupported_quit_on_open = mode == "drop" or mode == "tab_drop" or mode == "edit_in_place" - if not mode_unsupported_quit_on_open and edit_opts.quit_on_open then - view.close(cur_tabpage) - end - - local mode_unsupported_focus = mode == "drop" or mode == "tab_drop" or mode == "edit_in_place" - local focus = edit_opts.focus == nil or edit_opts.focus == true - if not mode_unsupported_focus and not focus then - -- if mode == "tabnew" a new tab will be opened and we need to focus back to the previous tab - if mode == "tabnew" then - vim.cmd(":tabprev") - end - view.focus() - end -end - ----@param mode string ----@param toggle_group boolean? ----@return fun(node: Node, edit_opts: NodeEditOpts?) -local function open_or_expand_or_dir_up(mode, toggle_group) - ---@param node Node - ---@param edit_opts NodeEditOpts? - return function(node, edit_opts) - local root = node:as(RootNode) - local dir = node:as(DirectoryNode) - - if root or node.name == ".." then - wrap_explorer("change_dir")("..") - elseif dir then - dir:expand_or_collapse(toggle_group) - elseif not toggle_group then - edit(mode, node, edit_opts) - end - end -end - -Api.node.open.edit = wrap_node(open_or_expand_or_dir_up("edit")) -Api.node.open.drop = wrap_node(open_or_expand_or_dir_up("drop")) -Api.node.open.tab_drop = wrap_node(open_or_expand_or_dir_up("tab_drop")) -Api.node.open.replace_tree_buffer = wrap_node(open_or_expand_or_dir_up("edit_in_place")) -Api.node.open.no_window_picker = wrap_node(open_or_expand_or_dir_up("edit_no_picker")) -Api.node.open.vertical = wrap_node(open_or_expand_or_dir_up("vsplit")) -Api.node.open.vertical_no_picker = wrap_node(open_or_expand_or_dir_up("vsplit_no_picker")) -Api.node.open.horizontal = wrap_node(open_or_expand_or_dir_up("split")) -Api.node.open.horizontal_no_picker = wrap_node(open_or_expand_or_dir_up("split_no_picker")) -Api.node.open.tab = wrap_node(open_or_expand_or_dir_up("tabnew")) -Api.node.open.toggle_group_empty = wrap_node(open_or_expand_or_dir_up("toggle_group_empty", true)) -Api.node.open.preview = wrap_node(open_or_expand_or_dir_up("preview")) -Api.node.open.preview_no_picker = wrap_node(open_or_expand_or_dir_up("preview_no_picker")) - -Api.node.show_info_popup = wrap_node(actions.node.file_popup.toggle_file_info) -Api.node.run.cmd = wrap_node(actions.node.run_command.run_file_command) -Api.node.run.system = wrap_node(actions.node.system_open.fn) - -Api.node.navigate.sibling.next = wrap_node(actions.moves.sibling.fn("next")) -Api.node.navigate.sibling.prev = wrap_node(actions.moves.sibling.fn("prev")) -Api.node.navigate.sibling.first = wrap_node(actions.moves.sibling.fn("first")) -Api.node.navigate.sibling.last = wrap_node(actions.moves.sibling.fn("last")) -Api.node.navigate.parent = wrap_node(actions.moves.parent.fn(false)) -Api.node.navigate.parent_close = wrap_node(actions.moves.parent.fn(true)) -Api.node.navigate.git.next = wrap_node(actions.moves.item.fn({ where = "next", what = "git" })) -Api.node.navigate.git.next_skip_gitignored = wrap_node(actions.moves.item.fn({ where = "next", what = "git", skip_gitignored = true })) -Api.node.navigate.git.next_recursive = wrap_node(actions.moves.item.fn({ where = "next", what = "git", recurse = true })) -Api.node.navigate.git.prev = wrap_node(actions.moves.item.fn({ where = "prev", what = "git" })) -Api.node.navigate.git.prev_skip_gitignored = wrap_node(actions.moves.item.fn({ where = "prev", what = "git", skip_gitignored = true })) -Api.node.navigate.git.prev_recursive = wrap_node(actions.moves.item.fn({ where = "prev", what = "git", recurse = true })) -Api.node.navigate.diagnostics.next = wrap_node(actions.moves.item.fn({ where = "next", what = "diag" })) -Api.node.navigate.diagnostics.next_recursive = wrap_node(actions.moves.item.fn({ where = "next", what = "diag", recurse = true })) -Api.node.navigate.diagnostics.prev = wrap_node(actions.moves.item.fn({ where = "prev", what = "diag" })) -Api.node.navigate.diagnostics.prev_recursive = wrap_node(actions.moves.item.fn({ where = "prev", what = "diag", recurse = true })) -Api.node.navigate.opened.next = wrap_node(actions.moves.item.fn({ where = "next", what = "opened" })) -Api.node.navigate.opened.prev = wrap_node(actions.moves.item.fn({ where = "prev", what = "opened" })) - -Api.node.expand = wrap_node(wrap_explorer("expand_node")) -Api.node.collapse = wrap_node(actions.tree.collapse.node) +---Please do not require or use modules other than `nvim-tree.api`, as internal modules will change without notice. +--- +---The API is separated into multiple modules: +--- +---- [nvim-tree-api-commands] +---- [nvim-tree-api-events] +---- [nvim-tree-api-filter] +---- [nvim-tree-api-fs] +---- [nvim-tree-api-git] +---- [nvim-tree-api-health] +---- [nvim-tree-api-map] +---- [nvim-tree-api-marks] +---- [nvim-tree-api-node] +---- [nvim-tree-api-tree] +--- +---Modules are accessed via `api..` +--- +---Example invocation of the `reload` function in the `tree` module: +---```lua +--- +---local api = require("nvim-tree.api") +---api.tree.reload() +---``` +---Generally, functions accepting a [nvim_tree.api.Node] as their first argument will use the node under the cursor when that argument is not present or nil. e.g. the following are functionally identical: +---```lua +--- +---api.node.open.edit(nil, { focus = true }) +--- +---api.node.open.edit(api.tree.get_node_under_cursor(), { focus = true }) +---``` ----@class ApiNodeDeleteWipeBufferOpts ----@field force boolean|nil default false -Api.node.buffer.delete = wrap_node(function(node, opts) - actions.node.buffer.delete(node, opts) -end) -Api.node.buffer.wipe = wrap_node(function(node, opts) - actions.node.buffer.wipe(node, opts) -end) -Api.git.reload = wrap_explorer("reload_git") +---The Node class is a data class. Instances may be provided by API functions for use as a: +---- handle to pass back to API functions e.g. [nvim_tree.api.node.run.cmd()] +---- reference in callbacks e.g. [nvim_tree.config.sort.Sorter] {sorter} +--- +---Please do not mutate the contents of any Node object. +--- +---@class nvim_tree.api.Node +---@field absolute_path string of the file or directory +---@field name string file or directory name +---@field parent? nvim_tree.api.DirectoryNode parent directory, nil for root +---@field type "file" | "directory" | "link" [uv.fs_stat()] {type} +---@field executable boolean file is executable +---@field fs_stat? uv.fs_stat.result at time of last tree display, see [uv.fs_stat()] +---@field git_status nvim_tree.git.Status? for files and directories +---@field diag_severity? lsp.DiagnosticSeverity diagnostic status +---@field hidden boolean node is not visible in the tree -Api.events.subscribe = events.subscribe -Api.events.Event = events.Event -Api.live_filter.start = wrap_explorer_member("live_filter", "start_filtering") -Api.live_filter.clear = wrap_explorer_member("live_filter", "clear_filter") -Api.marks.get = wrap_node(wrap_explorer_member("marks", "get")) -Api.marks.list = wrap_explorer_member("marks", "list") -Api.marks.toggle = wrap_node(wrap_explorer_member("marks", "toggle")) -Api.marks.clear = wrap_explorer_member("marks", "clear") -Api.marks.bulk.delete = wrap_explorer_member("marks", "bulk_delete") -Api.marks.bulk.trash = wrap_explorer_member("marks", "bulk_trash") -Api.marks.bulk.move = wrap_explorer_member("marks", "bulk_move") -Api.marks.navigate.next = wrap_explorer_member("marks", "navigate_next") -Api.marks.navigate.prev = wrap_explorer_member("marks", "navigate_prev") -Api.marks.navigate.select = wrap_explorer_member("marks", "navigate_select") +--- +---Git statuses for a single node. +--- +---`nvim_tree.git.XY`: 2 character string, see `man 1 git-status` "Short Format" +---@alias nvim_tree.git.XY string +--- +---{dir} status is derived from its contents: +---- `direct`: inherited from child files +---- `indirect`: inherited from child directories +--- +---@class nvim_tree.git.Status +---@field file? nvim_tree.git.XY status of a file node +---@field dir? table<"direct" | "indirect", nvim_tree.git.XY[]> direct inclusive-or indirect status + + + +-- +-- Load the (empty) meta definitions +-- +local deprecated = require("nvim-tree._meta.api.deprecated") + +---nvim-tree Public API +---@class nvim_tree.api +---@nodoc +local api = { + commands = require("nvim-tree._meta.api.commands"), + events = require("nvim-tree._meta.api.events"), + filter = require("nvim-tree._meta.api.filter"), + fs = require("nvim-tree._meta.api.fs"), + git = require("nvim-tree._meta.api._git"), + health = require("nvim-tree._meta.api.health"), + map = require("nvim-tree._meta.api.map"), + marks = require("nvim-tree._meta.api.marks"), + node = require("nvim-tree._meta.api.node"), + tree = require("nvim-tree._meta.api.tree"), + + config = deprecated.config, ---@deprecated + diagnostics = deprecated.diagnostics, ---@deprecated + live_filter = deprecated.live_filter, ---@deprecated +} -Api.config.mappings.get_keymap = wrap(keymap.get_keymap) -Api.config.mappings.get_keymap_default = wrap(keymap.get_keymap_default) -Api.config.mappings.default_on_attach = keymap.default_on_attach -Api.diagnostics.hi_test = wrap(appearance_hi_test) +-- +-- Map before-setup implementations, most throw an error notification "nvim-tree setup not called". +-- +require("nvim-tree.api.impl.pre")(api) -Api.commands.get = wrap(function() - return require("nvim-tree.commands").get() -end) ----Create a decorator class by calling :extend() ----See :help nvim-tree-decorators ----@type nvim_tree.api.decorator.UserDecorator -Api.decorator.UserDecorator = UserDecorator --[[@as nvim_tree.api.decorator.UserDecorator]] -return Api +return api diff --git a/lua/nvim-tree/api/impl/post.lua b/lua/nvim-tree/api/impl/post.lua new file mode 100644 index 00000000000..3f9793694d3 --- /dev/null +++ b/lua/nvim-tree/api/impl/post.lua @@ -0,0 +1,262 @@ +---Hydrates all API functions with concrete implementations. +---All "nvim-tree setup not called" error functions from pre.lua will be replaced. +--- +---Call this after nvim-tree setup +--- +---This is expensive as there are many cascading requires and is avoided +---until after setup has been called, so that the user may require API cheaply. + +local view = require("nvim-tree.view") +local actions = require("nvim-tree.actions") + +local DirectoryNode = require("nvim-tree.node.directory") +local FileLinkNode = require("nvim-tree.node.file-link") +local RootNode = require("nvim-tree.node.root") + +---Invoke a method on the singleton explorer. +---Print error when setup not called. +---@param explorer_method string explorer method name +---@return fun(...): any +local function wrap_explorer(explorer_method) + return function(...) + local explorer = require("nvim-tree.core").get_explorer() + if explorer then + return explorer[explorer_method](explorer, ...) + end + end +end + +---Inject the node as the first argument if present otherwise do nothing. +---@param fn fun(node: Node, ...): any +---@return fun(node: Node?, ...): any +local function wrap_node(fn) + return function(node, ...) + node = node or wrap_explorer("get_node_at_cursor")() + if node then + return fn(node, ...) + end + end +end + +---Inject the node or nil as the first argument if absent. +---@param fn fun(node: Node?, ...): any +---@return fun(node: Node?, ...): any +local function wrap_node_or_nil(fn) + return function(node, ...) + node = node or wrap_explorer("get_node_at_cursor")() + return fn(node, ...) + end +end + +---Invoke a member's method on the singleton explorer. +---Print error when setup not called. +---@param explorer_member string explorer member name +---@param member_method string method name to invoke on member +---@param ... any passed to method +---@return fun(...): any +local function wrap_explorer_member_args(explorer_member, member_method, ...) + local method_args = ... + return function(...) + local explorer = require("nvim-tree.core").get_explorer() + if explorer then + return explorer[explorer_member][member_method](explorer[explorer_member], method_args, ...) + end + end +end + +---Invoke a member's method on the singleton explorer. +---Print error when setup not called. +---@param explorer_member string explorer member name +---@param member_method string method name to invoke on member +---@return fun(...): any +local function wrap_explorer_member(explorer_member, member_method) + return function(...) + local explorer = require("nvim-tree.core").get_explorer() + if explorer then + return explorer[explorer_member][member_method](explorer[explorer_member], ...) + end + end +end + +---@class NodeEditOpts +---@field quit_on_open boolean|nil default false +---@field focus boolean|nil default true + +---@param mode string +---@param node Node +---@param edit_opts NodeEditOpts? +local function edit(mode, node, edit_opts) + local file_link = node:as(FileLinkNode) + local path = file_link and file_link.link_to or node.absolute_path + local cur_tabpage = vim.api.nvim_get_current_tabpage() + + actions.node.open_file.fn(mode, path) + + edit_opts = edit_opts or {} + + local mode_unsupported_quit_on_open = mode == "drop" or mode == "tab_drop" or mode == "edit_in_place" + if not mode_unsupported_quit_on_open and edit_opts.quit_on_open then + view.close(cur_tabpage) + end + + local mode_unsupported_focus = mode == "drop" or mode == "tab_drop" or mode == "edit_in_place" + local focus = edit_opts.focus == nil or edit_opts.focus == true + if not mode_unsupported_focus and not focus then + -- if mode == "tabnew" a new tab will be opened and we need to focus back to the previous tab + if mode == "tabnew" then + vim.cmd(":tabprev") + end + view.focus() + end +end + +---@param mode string +---@param toggle_group boolean? +---@return fun(node: Node, edit_opts: NodeEditOpts?) +local function open_or_expand_or_dir_up(mode, toggle_group) + ---@param node Node + ---@param edit_opts NodeEditOpts? + return function(node, edit_opts) + local root = node:as(RootNode) + local dir = node:as(DirectoryNode) + + if root or node.name == ".." then + wrap_explorer("change_dir")("..") + elseif dir then + dir:expand_or_collapse(toggle_group) + elseif not toggle_group then + edit(mode, node, edit_opts) + end + end +end + +---Hydrate all implementations barring those that were called during hydrate_pre +---@param api table +local function hydrate_post(api) + api.tree.open = actions.tree.open.fn + api.tree.focus = api.tree.open + + api.tree.toggle = actions.tree.toggle.fn + api.tree.close = view.close + api.tree.close_in_this_tab = view.close_this_tab_only + api.tree.close_in_all_tabs = view.close_all_tabs + api.tree.reload = wrap_explorer("reload_explorer") + + api.tree.resize = actions.tree.resize.fn + + api.tree.change_root = require("nvim-tree").change_dir + + api.tree.change_root_to_node = wrap_node(wrap_explorer("change_dir_to_node")) + api.tree.change_root_to_parent = wrap_node(wrap_explorer("dir_up")) + api.tree.get_node_under_cursor = wrap_explorer("get_node_at_cursor") + api.tree.get_nodes = wrap_explorer("get_nodes") + + api.tree.find_file = actions.tree.find_file.fn + api.tree.search_node = actions.finders.search_node.fn + + api.tree.collapse_all = actions.tree.collapse.all + + api.tree.expand_all = wrap_node(wrap_explorer("expand_all")) + api.tree.toggle_help = function() require("nvim-tree.help").toggle() end + api.tree.is_tree_buf = function() require("nvim-tree.utils").is_nvim_tree_buf() end + + api.tree.is_visible = view.is_visible + + api.tree.winid = view.winid + + api.fs.create = wrap_node_or_nil(actions.fs.create_file.fn) + api.fs.remove = wrap_node(actions.fs.remove_file.fn) + api.fs.trash = wrap_node(actions.fs.trash.fn) + api.fs.rename_node = wrap_node(actions.fs.rename_file.fn(":t")) + api.fs.rename = wrap_node(actions.fs.rename_file.fn(":t")) + api.fs.rename_sub = wrap_node(actions.fs.rename_file.fn(":p:h")) + api.fs.rename_basename = wrap_node(actions.fs.rename_file.fn(":t:r")) + api.fs.rename_full = wrap_node(actions.fs.rename_file.fn(":p")) + api.fs.cut = wrap_node(wrap_explorer_member("clipboard", "cut")) + api.fs.paste = wrap_node(wrap_explorer_member("clipboard", "paste")) + api.fs.clear_clipboard = wrap_explorer_member("clipboard", "clear_clipboard") + api.fs.print_clipboard = wrap_explorer_member("clipboard", "print_clipboard") + api.fs.copy.node = wrap_node(wrap_explorer_member("clipboard", "copy")) + api.fs.copy.absolute_path = wrap_node(wrap_explorer_member("clipboard", "copy_absolute_path")) + api.fs.copy.filename = wrap_node(wrap_explorer_member("clipboard", "copy_filename")) + api.fs.copy.basename = wrap_node(wrap_explorer_member("clipboard", "copy_basename")) + api.fs.copy.relative_path = wrap_node(wrap_explorer_member("clipboard", "copy_path")) + + api.node.open.edit = wrap_node(open_or_expand_or_dir_up("edit")) + api.node.open.drop = wrap_node(open_or_expand_or_dir_up("drop")) + api.node.open.tab_drop = wrap_node(open_or_expand_or_dir_up("tab_drop")) + api.node.open.replace_tree_buffer = wrap_node(open_or_expand_or_dir_up("edit_in_place")) + api.node.open.no_window_picker = wrap_node(open_or_expand_or_dir_up("edit_no_picker")) + api.node.open.vertical = wrap_node(open_or_expand_or_dir_up("vsplit")) + api.node.open.vertical_no_picker = wrap_node(open_or_expand_or_dir_up("vsplit_no_picker")) + api.node.open.horizontal = wrap_node(open_or_expand_or_dir_up("split")) + api.node.open.horizontal_no_picker = wrap_node(open_or_expand_or_dir_up("split_no_picker")) + api.node.open.tab = wrap_node(open_or_expand_or_dir_up("tabnew")) + api.node.open.toggle_group_empty = wrap_node(open_or_expand_or_dir_up("toggle_group_empty", true)) + api.node.open.preview = wrap_node(open_or_expand_or_dir_up("preview")) + api.node.open.preview_no_picker = wrap_node(open_or_expand_or_dir_up("preview_no_picker")) + + api.node.show_info_popup = wrap_node(actions.node.file_popup.toggle_file_info) + api.node.run.cmd = wrap_node(actions.node.run_command.run_file_command) + api.node.run.system = wrap_node(actions.node.system_open.fn) + + api.node.navigate.sibling.next = wrap_node(actions.moves.sibling.fn("next")) + api.node.navigate.sibling.prev = wrap_node(actions.moves.sibling.fn("prev")) + api.node.navigate.sibling.first = wrap_node(actions.moves.sibling.fn("first")) + api.node.navigate.sibling.last = wrap_node(actions.moves.sibling.fn("last")) + api.node.navigate.parent = wrap_node(actions.moves.parent.fn(false)) + api.node.navigate.parent_close = wrap_node(actions.moves.parent.fn(true)) + api.node.navigate.git.next = wrap_node(actions.moves.item.fn({ where = "next", what = "git" })) + api.node.navigate.git.next_skip_gitignored = wrap_node(actions.moves.item.fn({ where = "next", what = "git", skip_gitignored = true })) + api.node.navigate.git.next_recursive = wrap_node(actions.moves.item.fn({ where = "next", what = "git", recurse = true })) + api.node.navigate.git.prev = wrap_node(actions.moves.item.fn({ where = "prev", what = "git" })) + api.node.navigate.git.prev_skip_gitignored = wrap_node(actions.moves.item.fn({ where = "prev", what = "git", skip_gitignored = true })) + api.node.navigate.git.prev_recursive = wrap_node(actions.moves.item.fn({ where = "prev", what = "git", recurse = true })) + api.node.navigate.diagnostics.next = wrap_node(actions.moves.item.fn({ where = "next", what = "diag" })) + api.node.navigate.diagnostics.next_recursive = wrap_node(actions.moves.item.fn({ where = "next", what = "diag", recurse = true })) + api.node.navigate.diagnostics.prev = wrap_node(actions.moves.item.fn({ where = "prev", what = "diag" })) + api.node.navigate.diagnostics.prev_recursive = wrap_node(actions.moves.item.fn({ where = "prev", what = "diag", recurse = true })) + api.node.navigate.opened.next = wrap_node(actions.moves.item.fn({ where = "next", what = "opened" })) + api.node.navigate.opened.prev = wrap_node(actions.moves.item.fn({ where = "prev", what = "opened" })) + + api.node.expand = wrap_node(wrap_explorer("expand_node")) + api.node.collapse = wrap_node(actions.tree.collapse.node) + + api.node.buffer.delete = wrap_node(function(node, opts) actions.node.buffer.delete(node, opts) end) + api.node.buffer.wipe = wrap_node(function(node, opts) actions.node.buffer.wipe(node, opts) end) + + api.tree.reload_git = wrap_explorer("reload_git") + + api.filter.live.start = wrap_explorer_member("live_filter", "start_filtering") + api.filter.live.clear = wrap_explorer_member("live_filter", "clear_filter") + api.filter.toggle = wrap_explorer_member("filters", "toggle") + api.filter.git.ignored.toggle = wrap_explorer_member_args("filters", "toggle", "git_ignored") + api.filter.git.clean.toggle = wrap_explorer_member_args("filters", "toggle", "git_clean") + api.filter.no_buffer.toggle = wrap_explorer_member_args("filters", "toggle", "no_buffer") + api.filter.custom.toggle = wrap_explorer_member_args("filters", "toggle", "custom") + api.filter.dotfiles.toggle = wrap_explorer_member_args("filters", "toggle", "dotfiles") + api.filter.no_bookmark.toggle = wrap_explorer_member_args("filters", "toggle", "no_bookmark") + + api.marks.get = wrap_node(wrap_explorer_member("marks", "get")) + api.marks.list = wrap_explorer_member("marks", "list") + api.marks.toggle = wrap_node(wrap_explorer_member("marks", "toggle")) + api.marks.clear = wrap_explorer_member("marks", "clear") + api.marks.bulk.delete = wrap_explorer_member("marks", "bulk_delete") + api.marks.bulk.trash = wrap_explorer_member("marks", "bulk_trash") + api.marks.bulk.move = wrap_explorer_member("marks", "bulk_move") + api.marks.navigate.next = wrap_explorer_member("marks", "navigate_next") + api.marks.navigate.prev = wrap_explorer_member("marks", "navigate_prev") + api.marks.navigate.select = wrap_explorer_member("marks", "navigate_select") + + api.map.get_keymap = function() require("nvim-tree.keymap").get_keymap() end +end + +---Re-hydrate api +---@param api table +return function(api) + -- All concrete implementations + hydrate_post(api) + + -- (Re)hydrate any legacy by mapping to function set above + require("nvim-tree.legacy").api_map(api) +end diff --git a/lua/nvim-tree/api/impl/pre.lua b/lua/nvim-tree/api/impl/pre.lua new file mode 100644 index 00000000000..8df356584f3 --- /dev/null +++ b/lua/nvim-tree/api/impl/pre.lua @@ -0,0 +1,77 @@ +--Hydrates meta api empty definition functions with a new function: +-- - Default: error notification "nvim-tree setup not called". +-- - Exceptions: concrete implementation for API that can be called before setup. +-- +--Call it once when api is first required +-- +--This file should have minimal requires that are cheap and have no dependencies or are already required. +-- +--Everything must be as lazily loaded as possible: the user must be able to require api cheaply. + +local commands = require("nvim-tree.commands") -- already required by plugin.lua +local events = require("nvim-tree.events") -- needed for event registration pre-setup +local keymap = require("nvim-tree.keymap") -- needed for default on attach +local notify = require("nvim-tree.notify") -- already required by events and others + +local UserDecorator = require("nvim-tree.renderer.decorator.user") + +---Walk the api, hydrating all functions with the error notification +---@param t table api root or sub-module +local function hydrate_error(t) + for k, v in pairs(t) do + if type(v) == "function" then + t[k] = function() + notify.error("nvim-tree setup not called") + end + elseif type(v) == "table" then + hydrate_error(v) + end + end +end + +---Hydrate implementations that may be called pre setup +local function hydrate_pre(api) + -- + -- Essential + -- + api.events.Event = events.Event + api.events.subscribe = events.subscribe + + api.map.on_attach.default = keymap.on_attach_default + + + -- + -- May be lazily requried on execution + -- + api.health.hi_test = function() require("nvim-tree.appearance.hi-test")() end + + + -- + -- Already required elsewhere + -- + api.commands.get = commands.get + + api.map.get_keymap_default = keymap.get_keymap_default + + + -- + -- TODO #3241 + -- + api.decorator = {} + ---Create a decorator class by calling :extend() + ---See :help nvim-tree-decorators + ---@type nvim_tree.api.decorator.UserDecorator + api.decorator.UserDecorator = UserDecorator --[[@as nvim_tree.api.decorator.UserDecorator]] +end + +---Hydrate api +return function(api) + -- Default: error + hydrate_error(api) + + -- Exceptions: may be called + hydrate_pre(api) + + -- Hydrate any legacy by mapping to function set above + require("nvim-tree.legacy").api_map(api) +end diff --git a/lua/nvim-tree/commands.lua b/lua/nvim-tree/commands.lua index 8158465a4c7..1f788127aa9 100644 --- a/lua/nvim-tree/commands.lua +++ b/lua/nvim-tree/commands.lua @@ -1,5 +1,6 @@ local M = {} +---@type nvim_tree.api.commands.Command[] local CMDS = { { name = "NvimTreeOpen", @@ -108,7 +109,12 @@ local CMDS = { bar = true, }, command = function(c) - require("nvim-tree.view").resize(c.args) + local sign = c.args:sub(1, 1) + if sign == "+" or sign == "-" then + require("nvim-tree.api").tree.resize({ relative = tonumber(c.args) }) + else + require("nvim-tree.api").tree.resize({ absolute = tonumber(c.args) }) + end end, }, { @@ -118,7 +124,7 @@ local CMDS = { bar = true, }, command = function() - require("nvim-tree.api").tree.collapse_all(false) + require("nvim-tree.api").tree.collapse_all({ keep_buffers = false }) end, }, { @@ -128,7 +134,7 @@ local CMDS = { bar = true, }, command = function() - require("nvim-tree.api").tree.collapse_all(true) + require("nvim-tree.api").tree.collapse_all({ keep_buffers = true }) end, }, { @@ -137,11 +143,12 @@ local CMDS = { desc = "nvim-tree: highlight test", }, command = function() - require("nvim-tree.api").diagnostics.hi_test() + require("nvim-tree.api").health.hi_test() end, }, } +---@return nvim_tree.api.commands.Command[] function M.get() return vim.deepcopy(CMDS) end diff --git a/lua/nvim-tree/explorer/filters.lua b/lua/nvim-tree/explorer/filters.lua index f988dfc3170..43851954553 100644 --- a/lua/nvim-tree/explorer/filters.lua +++ b/lua/nvim-tree/explorer/filters.lua @@ -65,7 +65,7 @@ end ---Check if the given path is git clean/ignored ---@private ---@param path string Absolute path ----@param project GitProject from prepare +---@param project nvim_tree.git.Project from prepare ---@return boolean function Filters:git(path, project) if type(project) ~= "table" or type(project.files) ~= "table" or type(project.dirs) ~= "table" then @@ -195,7 +195,7 @@ function Filters:custom(path) end ---Prepare arguments for should_filter. This is done prior to should_filter for efficiency reasons. ----@param project GitProject? optional results of git.load_projects(...) +---@param project nvim_tree.git.Project? optional results of git.load_projects(...) ---@return table --- project: reference --- bufinfo: empty unless no_buffer set: vim.fn.getbufinfo { buflisted = 1 } diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 37cdeca36e7..532684e74fb 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -200,7 +200,7 @@ function Explorer:expand_dir_node(node) end ---@param node DirectoryNode ----@param project GitProject? +---@param project nvim_tree.git.Project? ---@return Node[]? function Explorer:reload(node, project) local cwd = node.link_to or node.absolute_path @@ -358,7 +358,7 @@ end ---@private ---@param nodes_by_path Node[] ---@param node_ignored boolean ----@param project GitProject? +---@param project nvim_tree.git.Project? ---@return fun(node: Node): Node function Explorer:update_git_statuses(nodes_by_path, node_ignored, project) return function(node) @@ -373,7 +373,7 @@ end ---@param handle uv.uv_fs_t ---@param cwd string ---@param node DirectoryNode ----@param project GitProject +---@param project nvim_tree.git.Project ---@param parent Explorer function Explorer:populate_children(handle, cwd, node, project, parent) local node_ignored = node:is_git_ignored() @@ -432,7 +432,7 @@ end ---@private ---@param node DirectoryNode ----@param project GitProject +---@param project nvim_tree.git.Project ---@param parent Explorer ---@return Node[]|nil function Explorer:explore(node, project, parent) @@ -467,7 +467,7 @@ function Explorer:explore(node, project, parent) end ---@private ----@param projects GitProject[] +---@param projects nvim_tree.git.Project[] function Explorer:refresh_nodes(projects) Iterator.builder({ self }) :applier(function(n) @@ -689,7 +689,7 @@ end ---Expand the directory node or the root ---@param node Node ----@param expand_opts ApiTreeExpandOpts? +---@param expand_opts? nvim_tree.api.node.expand.Opts function Explorer:expand_all(node, expand_opts) if node then node:expand(expand_opts) @@ -699,8 +699,8 @@ function Explorer:expand_all(node, expand_opts) end ---Expand the directory node or parent node ----@param node Node ----@param expand_opts ApiTreeExpandOpts? +---@param node? Node +---@param expand_opts? nvim_tree.api.node.expand.Opts function Explorer:expand_node(node, expand_opts) if not node then return diff --git a/lua/nvim-tree/git/init.lua b/lua/nvim-tree/git/init.lua index 6277a6a4f78..2ad0243ed06 100644 --- a/lua/nvim-tree/git/init.lua +++ b/lua/nvim-tree/git/init.lua @@ -7,34 +7,26 @@ local Watcher = require("nvim-tree.watcher").Watcher local Iterator = require("nvim-tree.iterators.node-iterator") local DirectoryNode = require("nvim-tree.node.directory") ----Git short format status xy ----@alias GitXY string - -- Git short-format status ----@alias GitPathXY table +---@alias nvim_tree.git.PathXY table -- Git short-format statuses ----@alias GitPathXYs table - ----Git short-format statuses for a single node ----@class (exact) GitNodeStatus ----@field file GitXY? ----@field dir table<"direct" | "indirect", GitXY[]>? +---@alias nvim_tree.git.PathXYs table ---Git state for an entire repo ----@class (exact) GitProject ----@field files GitProjectFiles? ----@field dirs GitProjectDirs? +---@class (exact) nvim_tree.git.Project +---@field files nvim_tree.git.ProjectFiles? +---@field dirs nvim_tree.git.ProjectDirs? ---@field watcher Watcher? ----@alias GitProjectFiles GitPathXY ----@alias GitProjectDirs table<"direct" | "indirect", GitPathXYs> +---@alias nvim_tree.git.ProjectFiles nvim_tree.git.PathXY +---@alias nvim_tree.git.ProjectDirs table<"direct" | "indirect", nvim_tree.git.PathXYs> local M = { config = {}, ---all projects keyed by toplevel - ---@type table + ---@type table _projects_by_toplevel = {}, ---index of paths inside toplevels, false when not inside a project @@ -58,8 +50,8 @@ local WATCHED_FILES = { ---@param toplevel string|nil ---@param path string|nil ----@param project GitProject ----@param project_files GitProjectFiles? +---@param project nvim_tree.git.Project +---@param project_files nvim_tree.git.ProjectFiles? local function reload_git_project(toplevel, path, project, project_files) if path then for p in pairs(project.files) do @@ -77,7 +69,7 @@ end --- Is this path in a known ignored directory? ---@param path string ----@param project GitProject +---@param project nvim_tree.git.Project ---@return boolean local function path_ignored_in_project(path, project) if not path or not project then @@ -94,7 +86,7 @@ local function path_ignored_in_project(path, project) return false end ----@return GitProject[] maybe empty +---@return nvim_tree.git.Project[] maybe empty function M.reload_all_projects() if not M.config.git.enable then return {} @@ -112,7 +104,7 @@ end ---@param path string? optional path to update only ---@param callback function? function M.reload_project(toplevel, path, callback) - local project = M._projects_by_toplevel[toplevel] --[[@as GitProject]] + local project = M._projects_by_toplevel[toplevel] --[[@as nvim_tree.git.Project]] if not toplevel or not project or not M.config.git.enable then if callback then @@ -138,7 +130,7 @@ function M.reload_project(toplevel, path, callback) } if callback then - ---@param path_xy GitPathXY + ---@param path_xy nvim_tree.git.PathXY args.callback = function(path_xy) reload_git_project(toplevel, path, project, path_xy) callback() @@ -152,7 +144,7 @@ end --- Retrieve a known project ---@param toplevel string? ----@return GitProject? project +---@return nvim_tree.git.Project? project function M.get_project(toplevel) return M._projects_by_toplevel[toplevel] end @@ -265,7 +257,7 @@ end --- Load the project status for a path. Does nothing when no toplevel for path. --- Only fetches project status when unknown, otherwise returns existing. ---@param path string absolute ----@return GitProject maybe empty +---@return nvim_tree.git.Project maybe empty function M.load_project(path) if not M.config.git.enable then return {} @@ -329,7 +321,7 @@ function M.load_project(path) end ---@param dir DirectoryNode ----@param project GitProject? +---@param project nvim_tree.git.Project? ---@param root string? function M.update_parent_projects(dir, project, root) while project and dir do @@ -378,7 +370,7 @@ function M.refresh_dir(dir) end ---@param dir DirectoryNode? ----@param projects GitProject[] +---@param projects nvim_tree.git.Project[] function M.reload_node_status(dir, projects) dir = dir and dir:as(DirectoryNode) if not dir or #dir.nodes == 0 then diff --git a/lua/nvim-tree/git/runner.lua b/lua/nvim-tree/git/runner.lua index 0c540575198..938d10fa0e0 100644 --- a/lua/nvim-tree/git/runner.lua +++ b/lua/nvim-tree/git/runner.lua @@ -10,8 +10,8 @@ local Class = require("nvim-tree.classic") ---@field private list_untracked boolean ---@field private list_ignored boolean ---@field private timeout integer ----@field private callback fun(path_xy: GitPathXY)? ----@field private path_xy GitPathXY +---@field private callback fun(path_xy: nvim_tree.git.PathXY)? +---@field private path_xy nvim_tree.git.PathXY ---@field private rc integer? -- -1 indicates timeout local GitRunner = Class:extend() @@ -24,7 +24,7 @@ local GitRunner = Class:extend() ---@field list_untracked boolean ---@field list_ignored boolean ---@field timeout integer ----@field callback fun(path_xy: GitPathXY)? +---@field callback fun(path_xy: nvim_tree.git.PathXY)? local timeouts = 0 local MAX_TIMEOUTS = 5 @@ -229,7 +229,7 @@ end ---Return nil when callback present ---@private ----@return GitPathXY? +---@return nvim_tree.git.PathXY? function GitRunner:execute() local async = self.callback ~= nil local profile = log.profile_start("git %s job %s %s", async and "async" or "sync", self.toplevel, self.path) @@ -263,7 +263,7 @@ end ---Static method to run a git process, which will be killed if it takes more than timeout ---Return nil when callback present ---@param args GitRunnerArgs ----@return GitPathXY? +---@return nvim_tree.git.PathXY? function GitRunner:run(args) local runner = GitRunner(args) diff --git a/lua/nvim-tree/git/utils.lua b/lua/nvim-tree/git/utils.lua index 1e3444c70f4..ca2bf0f6132 100644 --- a/lua/nvim-tree/git/utils.lua +++ b/lua/nvim-tree/git/utils.lua @@ -104,11 +104,11 @@ local function nil_insert(t, k) return t end ----@param project_files GitProjectFiles +---@param project_files nvim_tree.git.ProjectFiles ---@param cwd string|nil ----@return GitProjectDirs +---@return nvim_tree.git.ProjectDirs function M.project_files_to_project_dirs(project_files, cwd) - ---@type GitProjectDirs + ---@type nvim_tree.git.ProjectDirs local project_dirs = {} project_dirs.direct = {} @@ -145,12 +145,12 @@ end ---Git file status for an absolute path ---@param parent_ignored boolean ----@param project GitProject? +---@param project nvim_tree.git.Project? ---@param path string ---@param path_fallback string? alternative file path when no other file status ----@return GitNodeStatus +---@return nvim_tree.git.Status function M.git_status_file(parent_ignored, project, path, path_fallback) - ---@type GitNodeStatus + ---@type nvim_tree.git.Status local ns if parent_ignored then @@ -170,12 +170,12 @@ end ---Git file and directory status for an absolute path ---@param parent_ignored boolean ----@param project GitProject? +---@param project nvim_tree.git.Project? ---@param path string ---@param path_fallback string? alternative file path when no other file status ----@return GitNodeStatus? +---@return nvim_tree.git.Status? function M.git_status_dir(parent_ignored, project, path, path_fallback) - ---@type GitNodeStatus? + ---@type nvim_tree.git.Status? local ns if parent_ignored then diff --git a/lua/nvim-tree/help.lua b/lua/nvim-tree/help.lua index a5a0dbd6b4a..f5a971e3546 100644 --- a/lua/nvim-tree/help.lua +++ b/lua/nvim-tree/help.lua @@ -45,7 +45,7 @@ local function tidy_lhs(lhs) end --- Remove prefix 'nvim-tree: ' ---- Hardcoded to keep default_on_attach simple +--- Hardcoded to keep on_attach_default simple ---@param desc string ---@return string local function tidy_desc(desc) diff --git a/lua/nvim-tree/keymap.lua b/lua/nvim-tree/keymap.lua index c3373741f22..64326b86ea3 100644 --- a/lua/nvim-tree/keymap.lua +++ b/lua/nvim-tree/keymap.lua @@ -1,7 +1,7 @@ local M = {} --- Apply mappings to a scratch buffer and return buffer local mappings ----@param fn fun(bufnr: integer) on_attach or default_on_attach +---@param fn fun(bufnr: integer) on_attach or on_attach_default ---@return table as per vim.api.nvim_buf_get_keymap local function generate_keymap(fn) -- create an unlisted scratch buffer @@ -26,11 +26,11 @@ end ---@return table function M.get_keymap_default() - return generate_keymap(M.default_on_attach) + return generate_keymap(M.on_attach_default) end ---@param bufnr integer -function M.default_on_attach(bufnr) +function M.on_attach_default(bufnr) local api = require("nvim-tree.api") local function opts(desc) @@ -43,7 +43,7 @@ function M.default_on_attach(bufnr) } end - -- BEGIN_DEFAULT_ON_ATTACH + -- BEGIN_ON_ATTACH_DEFAULT vim.keymap.set("n", "", api.tree.change_root_to_node, opts("CD")) vim.keymap.set("n", "", api.node.open.replace_tree_buffer, opts("Open: In Place")) vim.keymap.set("n", "", api.node.show_info_popup, opts("Info")) @@ -63,9 +63,9 @@ function M.default_on_attach(bufnr) vim.keymap.set("n", "bd", api.marks.bulk.delete, opts("Delete Bookmarked")) vim.keymap.set("n", "bt", api.marks.bulk.trash, opts("Trash Bookmarked")) vim.keymap.set("n", "bmv", api.marks.bulk.move, opts("Move Bookmarked")) - vim.keymap.set("n", "B", api.tree.toggle_no_buffer_filter, opts("Toggle Filter: No Buffer")) + vim.keymap.set("n", "B", api.filter.no_buffer.toggle, opts("Toggle Filter: No Buffer")) vim.keymap.set("n", "c", api.fs.copy.node, opts("Copy")) - vim.keymap.set("n", "C", api.tree.toggle_git_clean_filter, opts("Toggle Filter: Git Clean")) + vim.keymap.set("n", "C", api.filter.git.clean.toggle, opts("Toggle Filter: Git Clean")) vim.keymap.set("n", "[c", api.node.navigate.git.prev, opts("Prev Git")) vim.keymap.set("n", "]c", api.node.navigate.git.next, opts("Next Git")) vim.keymap.set("n", "d", api.fs.remove, opts("Delete")) @@ -74,17 +74,17 @@ function M.default_on_attach(bufnr) vim.keymap.set("n", "e", api.fs.rename_basename, opts("Rename: Basename")) vim.keymap.set("n", "]e", api.node.navigate.diagnostics.next, opts("Next Diagnostic")) vim.keymap.set("n", "[e", api.node.navigate.diagnostics.prev, opts("Prev Diagnostic")) - vim.keymap.set("n", "F", api.live_filter.clear, opts("Live Filter: Clear")) - vim.keymap.set("n", "f", api.live_filter.start, opts("Live Filter: Start")) + vim.keymap.set("n", "F", api.filter.live.clear, opts("Live Filter: Clear")) + vim.keymap.set("n", "f", api.filter.live.start, opts("Live Filter: Start")) vim.keymap.set("n", "g?", api.tree.toggle_help, opts("Help")) vim.keymap.set("n", "gy", api.fs.copy.absolute_path, opts("Copy Absolute Path")) vim.keymap.set("n", "ge", api.fs.copy.basename, opts("Copy Basename")) - vim.keymap.set("n", "H", api.tree.toggle_hidden_filter, opts("Toggle Filter: Dotfiles")) - vim.keymap.set("n", "I", api.tree.toggle_gitignore_filter, opts("Toggle Filter: Git Ignore")) + vim.keymap.set("n", "H", api.filter.dotfiles.toggle, opts("Toggle Filter: Dotfiles")) + vim.keymap.set("n", "I", api.filter.git.ignored.toggle, opts("Toggle Filter: Git Ignored")) vim.keymap.set("n", "J", api.node.navigate.sibling.last, opts("Last Sibling")) vim.keymap.set("n", "K", api.node.navigate.sibling.first, opts("First Sibling")) vim.keymap.set("n", "L", api.node.open.toggle_group_empty, opts("Toggle Group Empty")) - vim.keymap.set("n", "M", api.tree.toggle_no_bookmark_filter, opts("Toggle Filter: No Bookmark")) + vim.keymap.set("n", "M", api.filter.no_bookmark.toggle, opts("Toggle Filter: No Bookmark")) vim.keymap.set("n", "m", api.marks.toggle, opts("Toggle Bookmark")) vim.keymap.set("n", "o", api.node.open.edit, opts("Open")) vim.keymap.set("n", "O", api.node.open.no_window_picker, opts("Open: No Window Picker")) @@ -96,19 +96,19 @@ function M.default_on_attach(bufnr) vim.keymap.set("n", "s", api.node.run.system, opts("Run System")) vim.keymap.set("n", "S", api.tree.search_node, opts("Search")) vim.keymap.set("n", "u", api.fs.rename_full, opts("Rename: Full Path")) - vim.keymap.set("n", "U", api.tree.toggle_custom_filter, opts("Toggle Filter: Hidden")) + vim.keymap.set("n", "U", api.filter.custom.toggle, opts("Toggle Filter: Custom")) vim.keymap.set("n", "W", api.tree.collapse_all, opts("Collapse All")) vim.keymap.set("n", "x", api.fs.cut, opts("Cut")) vim.keymap.set("n", "y", api.fs.copy.filename, opts("Copy Name")) vim.keymap.set("n", "Y", api.fs.copy.relative_path, opts("Copy Relative Path")) vim.keymap.set("n", "<2-LeftMouse>", api.node.open.edit, opts("Open")) vim.keymap.set("n", "<2-RightMouse>", api.tree.change_root_to_node, opts("CD")) - -- END_DEFAULT_ON_ATTACH + -- END_ON_ATTACH_DEFAULT end function M.setup(opts) if type(opts.on_attach) ~= "function" then - M.on_attach = M.default_on_attach + M.on_attach = M.on_attach_default else M.on_attach = opts.on_attach end diff --git a/lua/nvim-tree/legacy.lua b/lua/nvim-tree/legacy.lua index 842700ba36b..72aad9e3d85 100644 --- a/lua/nvim-tree/legacy.lua +++ b/lua/nvim-tree/legacy.lua @@ -2,6 +2,10 @@ local notify = require("nvim-tree.notify") local M = {} +-- +--Functions +-- + --- Create empty sub-tables if not present ---@param tbl table to create empty inside of ---@param path string dot separated string of sub-tables @@ -50,6 +54,10 @@ local function move(src, src_path, src_pos, dst, dst_path, dst_pos, remove) end end +-- +--Config +-- + -- silently move, please add to help nvim-tree-legacy-opts local function refactored(opts) -- 2022/06/20 @@ -151,4 +159,33 @@ function M.migrate_legacy_options(opts) removed(opts) end +-- +--API +-- + +---Silently create new api entries pointing legacy functions to current +function M.api_map(api) + api.config = api.config or {} + api.config.mappings = api.config.mappings or {} + api.config.mappings.get_keymap = api.map.keymap.current + api.config.mappings.get_keymap_default = api.map.keymap.default + api.config.mappings.default_on_attach = api.map.on_attach.default + + api.live_filter = api.live_filter or {} + api.live_filter.start = api.filter.live.start + api.live_filter.clear = api.filter.live.clear + + api.tree = api.tree or {} + api.tree.toggle_enable_filters = api.filter.toggle + api.tree.toggle_gitignore_filter = api.filter.git.ignored.toggle + api.tree.toggle_git_clean_filter = api.filter.git.clean.toggle + api.tree.toggle_no_buffer_filter = api.filter.no_buffer.toggle + api.tree.toggle_custom_filter = api.filter.custom.toggle + api.tree.toggle_hidden_filter = api.filter.dotfiles.toggle + api.tree.toggle_no_bookmark_filter = api.filter.no_bookmark.toggle + + api.diagnostics = api.diagnostics or {} + api.diagnostics.hi_test = api.health.hi_test +end + return M diff --git a/lua/nvim-tree/node/directory-link.lua b/lua/nvim-tree/node/directory-link.lua index 8b365047819..6d503ad6d40 100644 --- a/lua/nvim-tree/node/directory-link.lua +++ b/lua/nvim-tree/node/directory-link.lua @@ -33,7 +33,7 @@ end ---Update the directory git_status of link target and the file status of the link itself ---@param parent_ignored boolean ----@param project GitProject? +---@param project nvim_tree.git.Project? function DirectoryLinkNode:update_git_status(parent_ignored, project) self.git_status = git_utils.git_status_dir(parent_ignored, project, self.link_to, self.absolute_path) end diff --git a/lua/nvim-tree/node/directory.lua b/lua/nvim-tree/node/directory.lua index 0642dc581d1..d53718085f9 100644 --- a/lua/nvim-tree/node/directory.lua +++ b/lua/nvim-tree/node/directory.lua @@ -58,12 +58,12 @@ end ---Update the git_status of the directory ---@param parent_ignored boolean ----@param project GitProject? +---@param project nvim_tree.git.Project? function DirectoryNode:update_git_status(parent_ignored, project) self.git_status = git_utils.git_status_dir(parent_ignored, project, self.absolute_path, nil) end ----@return GitXY[]? +---@return nvim_tree.git.XY[]? function DirectoryNode:get_git_xy() if not self.git_status or not self.explorer.opts.git.show_on_dirs then return nil @@ -354,7 +354,7 @@ local function descend_until_empty(_, node) return not should_exclude end ----@param expand_opts ApiTreeExpandOpts? +---@param expand_opts? nvim_tree.api.node.expand.Opts function DirectoryNode:expand(expand_opts) local expansion_count = 0 diff --git a/lua/nvim-tree/node/file-link.lua b/lua/nvim-tree/node/file-link.lua index b13c88f0d6b..6cb83e0343a 100644 --- a/lua/nvim-tree/node/file-link.lua +++ b/lua/nvim-tree/node/file-link.lua @@ -26,7 +26,7 @@ end ---Update the git_status of the target otherwise the link itself ---@param parent_ignored boolean ----@param project GitProject? +---@param project nvim_tree.git.Project? function FileLinkNode:update_git_status(parent_ignored, project) self.git_status = git_utils.git_status_file(parent_ignored, project, self.link_to, self.absolute_path) end diff --git a/lua/nvim-tree/node/file.lua b/lua/nvim-tree/node/file.lua index 6e160409c29..bba1621e21b 100644 --- a/lua/nvim-tree/node/file.lua +++ b/lua/nvim-tree/node/file.lua @@ -36,12 +36,12 @@ end ---Update the GitStatus of the file ---@param parent_ignored boolean ----@param project GitProject? +---@param project nvim_tree.git.Project? function FileNode:update_git_status(parent_ignored, project) self.git_status = git_utils.git_status_file(parent_ignored, project, self.absolute_path, nil) end ----@return GitXY[]? +---@return nvim_tree.git.XY[]? function FileNode:get_git_xy() if not self.git_status then return nil diff --git a/lua/nvim-tree/node/init.lua b/lua/nvim-tree/node/init.lua index ca08b8ad724..5aaf4fb094a 100644 --- a/lua/nvim-tree/node/init.lua +++ b/lua/nvim-tree/node/init.lua @@ -8,7 +8,7 @@ local Class = require("nvim-tree.classic") ---@field absolute_path string ---@field executable boolean ---@field fs_stat uv.fs_stat.result? ----@field git_status GitNodeStatus? +---@field git_status nvim_tree.git.Status? ---@field hidden boolean ---@field name string ---@field parent DirectoryNode? @@ -45,13 +45,13 @@ end ---Update the git_status of the node ---Abstract ---@param parent_ignored boolean ----@param project GitProject? +---@param project nvim_tree.git.Project? function Node:update_git_status(parent_ignored, project) self:nop(parent_ignored, project) end ---Short-format statuses ----@return GitXY[]? +---@return nvim_tree.git.XY[]? function Node:get_git_xy() end @@ -144,14 +144,15 @@ function Node:clone(api_nodes) return clone end ----@param _expansion_count integer ----@param _should_descend fun(expansion_count: integer, node: Node): boolean +---@param expansion_count integer +---@param should_descend fun(expansion_count: integer, node: Node): boolean ---@return boolean -function Node:should_expand(_expansion_count, _should_descend) +function Node:should_expand(expansion_count, should_descend) + self:nop(expansion_count, should_descend) return false end ----@param expand_opts ApiTreeExpandOpts? +---@param expand_opts? nvim_tree.api.node.expand.Opts function Node:expand(expand_opts) if self.parent then self.parent:expand(expand_opts) diff --git a/lua/nvim-tree/renderer/decorator/git.lua b/lua/nvim-tree/renderer/decorator/git.lua index 41a5d2fdf25..c117b16959d 100644 --- a/lua/nvim-tree/renderer/decorator/git.lua +++ b/lua/nvim-tree/renderer/decorator/git.lua @@ -9,13 +9,13 @@ local DirectoryNode = require("nvim-tree.node.directory") ---@alias GitStatusStrings "deleted" | "ignored" | "renamed" | "staged" | "unmerged" | "unstaged" | "untracked" ---@alias GitIconsByStatus table human status ----@alias GitIconsByXY table porcelain status +---@alias GitIconsByXY table porcelain status ---@alias GitGlyphsByStatus table from opts ---@class (exact) GitDecorator: Decorator ---@field private explorer Explorer ----@field private file_hl_by_xy table? ----@field private folder_hl_by_xy table? +---@field private file_hl_by_xy table? +---@field private folder_hl_by_xy table? ---@field private icons_by_status GitIconsByStatus? ---@field private icons_by_xy GitIconsByXY? local GitDecorator = Decorator:extend() diff --git a/lua/nvim-tree/view.lua b/lua/nvim-tree/view.lua index 275e68635d0..f906cba4ba2 100644 --- a/lua/nvim-tree/view.lua +++ b/lua/nvim-tree/view.lua @@ -487,8 +487,8 @@ function M.focus(winnr, open_if_closed) end --- Retrieve the winid of the open tree. ----@param opts ApiTreeWinIdOpts|nil ----@return number|nil winid unlike get_winnr(), this returns nil if the nvim-tree window is not visible +---@param opts? nvim_tree.api.tree.winid.Opts +---@return number? winid unlike get_winnr(), this returns nil if the nvim-tree window is not visible function M.winid(opts) local tabpage = opts and opts.tabpage if tabpage == 0 then diff --git a/scripts/gen_vimdoc_config.lua b/scripts/gen_vimdoc_config.lua index 1b730a299c0..691fe69bde8 100644 --- a/scripts/gen_vimdoc_config.lua +++ b/scripts/gen_vimdoc_config.lua @@ -6,8 +6,9 @@ ---@field helptag string must be globally unique ---@field section string arbitrary ---@field path string relative to root ----@field file_name string? generated from path ----@field name string? override generated name +---@field file_name? string generated from path +---@field name? string override generated name +---@field append_only? boolean follows previous section ---Help txt is deleted from first tag down and generated content is appended. ---@type Src[] @@ -35,7 +36,21 @@ local srcs = { { helptag = "nvim-tree-config-experimental", section = "Config: experimental", path = "./lua/nvim_tree/_meta/config/experimental.lua", }, { helptag = "nvim-tree-config-log", section = "Config: log", path = "./lua/nvim_tree/_meta/config/log.lua", }, - { helptag = "nvim-tree-default-config", section = "Config: Default", path = "./lua/nvim_tree/_meta/config/default.lua", }, + { helptag = "nvim-tree-config-default", section = "Config: Default", path = "./lua/nvim_tree/_meta/config/default.lua", }, + + { helptag = "nvim-tree-api", section = "API", path = "./lua/nvim_tree/api.lua", }, + + { helptag = "nvim-tree-api-commands", section = "API: commands", path = "./lua/nvim_tree/_meta/api/commands.lua", }, + { helptag = "nvim-tree-api-events", section = "API: events", path = "./lua/nvim_tree/_meta/api/events.lua", }, + { helptag = "nvim-tree-api-filter", section = "API: filter", path = "./lua/nvim_tree/_meta/api/filter.lua", }, + { helptag = "nvim-tree-api-fs", section = "API: fs", path = "./lua/nvim_tree/_meta/api/fs.lua", }, + -- TODO #3088 come up with a solution to avoid filename clashes + { helptag = "nvim-tree-api-git", section = "API: git", path = "./lua/nvim_tree/_meta/api/_git.lua", }, + { helptag = "nvim-tree-api-health", section = "API: health", path = "./lua/nvim_tree/_meta/api/health.lua", }, + { helptag = "nvim-tree-api-map", section = "API: map", path = "./lua/nvim_tree/_meta/api/map.lua", }, + { helptag = "nvim-tree-api-marks", section = "API: marks", path = "./lua/nvim_tree/_meta/api/marks.lua", }, + { helptag = "nvim-tree-api-node", section = "API: node", path = "./lua/nvim_tree/_meta/api/node.lua", }, + { helptag = "nvim-tree-api-tree", section = "API: tree", path = "./lua/nvim_tree/_meta/api/tree.lua", }, } -- hydrate file names @@ -63,6 +78,8 @@ local config = { -- path files = vim.tbl_map(function(src) return src.path end, srcs), + append_only = vim.tbl_map(function(src) return src.append_only and src.file_name or nil end, srcs), + section_fmt = function(name) print(string.format("section_fmt name=%s", name)) return srcs_by_name[name] and srcs_by_name[name].section or @@ -86,10 +103,13 @@ local config = { -- remove the API prefix from the left aligned function name -- this will cascade into fn_helptag_fmt, which will apply the module prefix anyway + + -- TODO #3088 come up with a solution to avoid filename clashes + ---@diagnostic disable-next-line: unused-local local name, replaced = fun.name:gsub("^" .. module .. "%.", "", 1) - if (replaced ~= 1) then - error(string.format("function name does not start with module: %s", vim.inspect(fun))) - end + -- if (replaced ~= 1) then + -- error(string.format("function name does not start with module: %s", vim.inspect(fun))) + -- end print(string.format("fn_xform name: %s -> %s", fun.name, name)) diff --git a/scripts/help-update.sh b/scripts/help-update.sh index 64580ba9ead..a367feb9e81 100755 --- a/scripts/help-update.sh +++ b/scripts/help-update.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -# run after changing default config or keymap.lua M.default_on_attach +# run after changing default config or keymap.lua M.on_attach_default # scrapes and updates nvim-tree-lua.txt # run from repository root: scripts/help-update.sh OR make help-update @@ -25,25 +25,25 @@ sed -i -e "/${inject}/r /tmp/DEFAULT_OPTS.6.lua" -e "/${inject}/d" doc/nvim-tree # Inject default mappings # -begin="BEGIN_DEFAULT_ON_ATTACH" -end="END_DEFAULT_ON_ATTACH" +begin="BEGIN_ON_ATTACH_DEFAULT" +end="END_ON_ATTACH_DEFAULT" -# scrape DEFAULT_ON_ATTACH, indented at 2 -sed -n -e "/${begin}/,/${end}/{ /${begin}/d; /${end}/d; p; }" lua/nvim-tree/keymap.lua > /tmp/DEFAULT_ON_ATTACH.lua +# scrape ON_ATTACH_DEFAULT, indented at 2 +sed -n -e "/${begin}/,/${end}/{ /${begin}/d; /${end}/d; p; }" lua/nvim-tree/keymap.lua > /tmp/ON_ATTACH_DEFAULT.lua # help lua -sed -i -e "/${begin}/,/${end}/{ /${begin}/{p; r /tmp/DEFAULT_ON_ATTACH.lua +sed -i -e "/${begin}/,/${end}/{ /${begin}/{p; r /tmp/ON_ATTACH_DEFAULT.lua }; /${end}/p; d; }" doc/nvim-tree-lua.txt # help human -echo > /tmp/DEFAULT_ON_ATTACH.help -sed -E "s/^ *vim.keymap.set\(\"n\", \"(.*)\",.*api(.*),.*opts\(\"(.*)\".*$/'\`\1\`' '\3' '|nvim-tree-api\2()|'/g -" /tmp/DEFAULT_ON_ATTACH.lua | while read -r line +echo > /tmp/ON_ATTACH_DEFAULT.help +sed -E "s/^ *vim.keymap.set\(\"n\", \"(.*)\",.*api(.*),.*opts\(\"(.*)\".*$/'\`\1\`' '\3' '|nvim_tree.api\2()|'/g +" /tmp/ON_ATTACH_DEFAULT.lua | while read -r line do - eval "printf '%-17.17s %-26.26s %s\n' ${line}" >> /tmp/DEFAULT_ON_ATTACH.help + eval "printf '%-17.17s %-26.26s %s\n' ${line}" >> /tmp/ON_ATTACH_DEFAULT.help done -echo >> /tmp/DEFAULT_ON_ATTACH.help +echo >> /tmp/ON_ATTACH_DEFAULT.help begin="Show the mappings:" end="======" -sed -i -e "/${begin}/,/${end}/{ /${begin}/{p; r /tmp/DEFAULT_ON_ATTACH.help +sed -i -e "/${begin}/,/${end}/{ /${begin}/{p; r /tmp/ON_ATTACH_DEFAULT.help }; /${end}/p; d; }" doc/nvim-tree-lua.txt diff --git a/scripts/lintdoc.sh b/scripts/lintdoc.sh index 7edcc5d1519..f85e4ff4a73 100755 --- a/scripts/lintdoc.sh +++ b/scripts/lintdoc.sh @@ -56,3 +56,6 @@ cd "${DIR_NVIM_SRC}" # make nvim and execute the lint make lintdoc + +# clean up +rm -v "${DIR_NVIM_SRC}/runtime/doc/nvim-tree-lua.txt"