From a71bb3ab916629f010565e11c52a8c9ca5b73394 Mon Sep 17 00:00:00 2001 From: Kiyan Date: Sat, 14 May 2022 09:54:27 +0200 Subject: [PATCH] # This is a combination of 14 commits.tree a88ac1bf9454ffa72e8002a79b25012996ed32f0 parent 46014449b6a452da805b3bfe164eb68f37124669 author Kiyan 1652514867 +0200 committer Moshe Avni 1653224067 +0300 # This is a combination of 13 commits. # This is the 1st commit message: feat(renderer): add ability to set git icons in signcolumn (#1242) # This is the commit message #2: feat: extension sorter (#1181) (#1264) # This is the commit message #3: Revert "#1253 only pad git icons when they are present (#1259)" This reverts commit 90d7b8edb1d715086b34572a0fb742faf23a271b. fixes #1267 # This is the commit message #4: fix(renderer): padding when git icons are after the name fixes #1253 # This is the commit message #5: fix(renderer): empty space at end of line fixes #1253 # This is the commit message #6: add fish performance tip to README.md # This is the commit message #7: feat(live-filter): add ability to live filter out nodes in the tree (#1056) # This is the commit message #8: feat: reload explorer on buf enter (#1265) # This is the commit message #9: chore(config): auto resize the tree by default when opening a file. config.open_file.auto_resize is now true by default. Breaking change for default configurations. See https://github.com/kyazdani42/nvim-tree.lua/issues/1275#issuecomment-1133515999 # This is the commit message #10: chore: remove custom set local implementation Seems vim.opt_local has been fixed. see https://github.com/neovim/neovim/issues/14670 # This is the commit message #11: refactor: simplify opening file in new tab fixes #1271. Also fixes opening a file in new tab when close_on_open was true. This introduces breaking change since we don't do any extra behavior and let the buffer be opened by the tree. The previous behavior was a bit old and i believe this should've been fixed by now. Reference this commit if unexpected behavior appears while opening files in new tabs from nvim-tree. # This is the commit message #12: feat: optional path argument for NvimTreeToggle and NvimTreeFindFileToggle (#1276) # This is the commit message #13: Ignore case when removing default mappings # This is the commit message #14: issue#362: File Management popup menu UI. First Iteration. --- README.md | 14 +- doc/nvim-tree-lua.txt | 53 +++++-- lua/nvim-tree.lua | 28 ++-- lua/nvim-tree/actions/find-file.lua | 48 ++++--- lua/nvim-tree/actions/init.lua | 15 +- lua/nvim-tree/actions/movements.lua | 68 +++------ lua/nvim-tree/actions/open-file.lua | 26 ---- lua/nvim-tree/colors.lua | 2 + lua/nvim-tree/core.lua | 4 + lua/nvim-tree/diagnostics.lua | 2 +- lua/nvim-tree/explorer/explore.lua | 2 + lua/nvim-tree/explorer/reload.lua | 2 + lua/nvim-tree/explorer/sorters.lua | 26 ++++ lua/nvim-tree/lib.lua | 12 +- lua/nvim-tree/live-filter.lua | 132 ++++++++++++++++++ lua/nvim-tree/popup-menu/init.lua | 112 +++++++++++++++ lua/nvim-tree/popup-menu/mappings.lua | 17 +++ lua/nvim-tree/popup-menu/scratch.lua | 7 + lua/nvim-tree/renderer/builder.lua | 71 ++++++++-- lua/nvim-tree/renderer/components/git.lua | 15 +- lua/nvim-tree/renderer/components/padding.lua | 6 +- lua/nvim-tree/renderer/init.lua | 14 +- lua/nvim-tree/utils.lua | 39 +++--- lua/nvim-tree/view.lua | 31 ++-- 24 files changed, 563 insertions(+), 183 deletions(-) create mode 100644 lua/nvim-tree/live-filter.lua create mode 100644 lua/nvim-tree/popup-menu/init.lua create mode 100644 lua/nvim-tree/popup-menu/mappings.lua create mode 100644 lua/nvim-tree/popup-menu/scratch.lua diff --git a/README.md b/README.md index e5886973aec..264060b6b84 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,7 @@ require'nvim-tree'.setup { -- BEGIN_DEFAULT_OPTS open_on_tab = false, sort_by = "name", update_cwd = false, + reload_on_bufenter = false, view = { width = 30, height = 30, @@ -156,7 +157,7 @@ require'nvim-tree'.setup { -- BEGIN_DEFAULT_OPTS icons = { webdev_colors = true, git_placement = "before", - } + }, }, hijack_directories = { enable = true, @@ -201,7 +202,7 @@ require'nvim-tree'.setup { -- BEGIN_DEFAULT_OPTS }, open_file = { quit_on_open = false, - resize_window = false, + resize_window = true, window_picker = { enable = true, chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", @@ -216,6 +217,10 @@ require'nvim-tree'.setup { -- BEGIN_DEFAULT_OPTS cmd = "trash", require_confirm = true, }, + live_filter = { + prefix = "[FILTER]: ", + always_show_folders = true, + }, log = { enable = false, truncate = false, @@ -269,6 +274,7 @@ require'nvim-tree'.setup { -- BEGIN_DEFAULT_OPTS - `S` will prompt the user to enter a path and then expands the tree to match the path - `.` will enter vim command mode with the file the cursor is on - `C-k` will toggle a popup with file infos about the file under the cursor +- `f` will allow you to filter nodes dynamically based on regex matching. ### Settings @@ -330,6 +336,8 @@ local list = { { key = "]c", action = "next_git_item" }, { key = "-", action = "dir_up" }, { key = "s", action = "system_open" }, + { key = "f", action = "live_filter" }, + { key = "F", action = "clear_live_filter" }, { key = "q", action = "close" }, { key = "g?", action = "toggle_help" }, { key = "W", action = "collapse_all" }, @@ -376,7 +384,7 @@ Please attach `$XDG_CACHE_HOME/nvim/nvim-tree.log` if you raise an issue. *Performance Tips:* -* If you are using fish as an editor shell (which might be fixed in the future), try set `shell=/bin/bash` in your vim config. +* If you are using fish as an editor shell (which might be fixed in the future), try set `shell=/bin/bash` in your vim config. Alternatively, you can [prevent fish from loading interactive configuration in a non-interactive shell](https://github.com/kyazdani42/nvim-tree.lua/issues/549#issuecomment-1127394585). * Try manually running the git command (see the logs) in your shell e.g. `git --no-optional-locks status --porcelain=v1 --ignored=matching -u`. diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index bf4927f11ee..389608676e8 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -31,7 +31,7 @@ closes the tree |:NvimTreeToggle| *:NvimTreeToggle* -open or close the tree +open or close the tree. Takes an optional path argument. |:NvimTreeFocus| *:NvimTreeFocus* @@ -52,7 +52,8 @@ It will also open the leafs of the tree leading to the file in the buffer |:NvimTreeFindFileToggle| *:NvimTreeFindFileToggle* close the tree or change the cursor in the tree for the current bufname, -similar to combination of |:NvimTreeToggle| and |:NvimTreeFindFile| +similar to combination of |:NvimTreeToggle| and |:NvimTreeFindFile|. Takes an +optional path argument. |:NvimTreeClipboard| *:NvimTreeClipboard* @@ -96,6 +97,7 @@ Values may be functions. Warning: this may result in unexpected behaviour. open_on_tab = false, sort_by = "name", update_cwd = false, + reload_on_bufenter = false, view = { width = 30, height = 30, @@ -124,7 +126,7 @@ Values may be functions. Warning: this may result in unexpected behaviour. icons = { webdev_colors = true, git_placement = "before", - } + }, }, hijack_directories = { enable = true, @@ -169,7 +171,7 @@ Values may be functions. Warning: this may result in unexpected behaviour. }, open_file = { quit_on_open = false, - resize_window = false, + resize_window = true, window_picker = { enable = true, chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", @@ -184,6 +186,10 @@ Values may be functions. Warning: this may result in unexpected behaviour. cmd = "trash", require_confirm = true, }, + live_filter = { + prefix = "[FILTER]: ", + always_show_folders = true, + }, log = { enable = false, truncate = false, @@ -228,7 +234,7 @@ Will ignore the buffer, when deciding to open the tree on setup. Type: `boolean`, Default: `false` *nvim-tree.ignore_ft_on_setup* -List of filetypes that will make `open_on_setup` not open. +List of filetypes that will make `open_on_setup` not open. You can use this option if you don't want the tree to open in some scenarios (eg using vim startify). Type: {string}, Default: {} @@ -244,7 +250,7 @@ if the tree was previously open. *nvim-tree.sort_by* Changes how files within the same directory are sorted. -Can be one of 'name', 'case_sensitive' or 'modification_time'. +Can be one of 'name', 'case_sensitive', 'modification_time' or 'extension'. Type: `string`, Default: `"name"` *nvim-tree.hijack_unnamed_buffer_when_opening* @@ -259,6 +265,10 @@ Keeps the cursor on the first letter of the filename when moving in the tree. Changes the tree root directory on `DirChanged` and refreshes the tree. Type: `boolean`, Default: `false` +*nvim-tree.reload_on_bufenter* +Automatically reloads the tree on `BufEnter` nvim-tree. + Type: `boolean`, Default: `false` + *nvim-tree.hijack_directories* hijacks new directory buffers when they are opened (`:e dir`). @@ -402,7 +412,7 @@ Window / buffer setup. Will use only the provided user mappings and not the default otherwise, extends the default mappings with the provided user mappings. Type: `boolean`, Default: `false` - + *nvim-tree.view.mappings.list* A list of keymaps that will extend or override the default keymaps. Type: list of { key: table of strings or string, mode: string (vim-mode), cb: callback function as a string } @@ -432,7 +442,10 @@ UI rendering setup *nvim-tree.renderer.icons.git_placement* Place where the git icons will be rendered. After or before the `filename` (after the file/folders icons). - Type: `after` or `before`, Default: `before` + When placed in the signcolumn, the value of signcolumn should be `yes` + for the nvim-tree window. + Note that the diagnostic signs will take precedence over the git signs. + Type: `after`, `before` or `signcolumn`, Default: `before` *nvim-tree.filters* Filtering options. @@ -487,7 +500,7 @@ Configuration for various actions. *nvim-tree.actions.open_file.resize_window* Resizes the tree when opening a file. - Type: `boolean`, Default: `false` + Type: `boolean`, Default: `true` *nvim-tree.actions.open_file.window_picker* Window picker configuration. @@ -516,6 +529,20 @@ Configuration for various actions. '+' (system), otherwise, it will be stored in '1' and '"'. Type: `boolean`, Default: `true` +*nvim-tree.live_filter* +Configurations for the live_filtering feature. +The 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. + + *nvim-tree.live_filter.prefix* + Prefix of the filter displayed in the buffer. + Type: `string`, Default: `"[FILTER]: "` + + *nvim-tree.live_filter.always_show_folders* + Wether to filter folders or not. + Type: `boolean`, Default: `true` *nvim-tree.log* Configuration for diagnostic logging. @@ -761,6 +788,8 @@ Defaults to: { key = "]c", action = "next_git_item" }, { key = "-", action = "dir_up" }, { key = "s", action = "system_open" }, + { key = "f", action = "live_filter" }, + { key = "F", action = "clear_live_filter" }, { key = "q", action = "close" }, { key = "g?", action = "toggle_help" }, { key = 'W', action = "collapse_all" }, @@ -770,6 +799,7 @@ Defaults to: { key = "U", action = "toggle_custom" }, } < + The `list` option in `view.mappings.list` is a table of - key can be either a string or a table of string (lhs) @@ -876,6 +906,11 @@ NvimTreeFileRenamed NvimTreeFileNew NvimTreeFileDeleted +There are 2 highlight groups for the live filter feature + +NvimTreeLiveFilterPrefix +NvimTreeLiveFilterValue + ============================================================================== vinegar style *nvim-tree-vinegar* diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 81326b52c71..c166afddfc4 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -26,12 +26,12 @@ end ---@deprecated M.on_keypress = require("nvim-tree.actions").on_keypress -function M.toggle(find_file, no_focus) +function M.toggle(find_file, no_focus, cwd) if view.is_visible() then view.close() else local previous_buf = api.nvim_get_current_buf() - M.open() + M.open(cwd) if _config.update_focused_file.enable or find_file then M.find_file(false, previous_buf) end @@ -259,18 +259,18 @@ local function setup_vim_commands() M.open(res.args) end, { nargs = "?", complete = "dir" }) api.nvim_create_user_command("NvimTreeClose", view.close, {}) - api.nvim_create_user_command("NvimTreeToggle", function() - M.toggle(false) - end, {}) + api.nvim_create_user_command("NvimTreeToggle", function(res) + M.toggle(false, false, res.args) + end, { nargs = "?", complete = "dir" }) api.nvim_create_user_command("NvimTreeFocus", M.focus, {}) api.nvim_create_user_command("NvimTreeRefresh", reloaders.reload_explorer, {}) api.nvim_create_user_command("NvimTreeClipboard", copy_paste.print_clipboard, {}) api.nvim_create_user_command("NvimTreeFindFile", function() M.find_file(true) end, {}) - api.nvim_create_user_command("NvimTreeFindFileToggle", function() - M.toggle(true) - end, {}) + api.nvim_create_user_command("NvimTreeFindFileToggle", function(res) + M.toggle(true, false, res.args) + end, { nargs = "?", complete = "dir" }) api.nvim_create_user_command("NvimTreeResize", function(res) M.resize(res.args) end, { nargs = 1 }) @@ -336,6 +336,10 @@ local function setup_autocommands(opts) if opts.hijack_directories.enable then create_nvim_tree_autocmd({ "BufEnter", "BufNewFile" }, { callback = M.open_on_directory }) end + + if opts.reload_on_bufenter then + create_nvim_tree_autocmd("BufEnter", { pattern = "NvimTree_*", callback = reloaders.reload_explorer }) + end end local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS @@ -350,6 +354,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS open_on_tab = false, sort_by = "name", update_cwd = false, + reload_on_bufenter = false, view = { width = 30, height = 30, @@ -423,7 +428,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS }, open_file = { quit_on_open = false, - resize_window = false, + resize_window = true, window_picker = { enable = true, chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", @@ -438,6 +443,10 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS cmd = "trash", require_confirm = true, }, + live_filter = { + prefix = "[FILTER]: ", + always_show_folders = true, + }, log = { enable = false, truncate = false, @@ -538,6 +547,7 @@ function M.setup(conf) require("nvim-tree.view").setup(opts) require("nvim-tree.lib").setup(opts) require("nvim-tree.renderer").setup(opts) + require("nvim-tree.live-filter").setup(opts) setup_vim_commands() setup_autocommands(opts) diff --git a/lua/nvim-tree/actions/find-file.lua b/lua/nvim-tree/actions/find-file.lua index e07d52af213..1f5e78a237b 100644 --- a/lua/nvim-tree/actions/find-file.lua +++ b/lua/nvim-tree/actions/find-file.lua @@ -29,35 +29,37 @@ function M.fn(fname) local function iterate_nodes(nodes) for _, node in ipairs(nodes) do - i = i + 1 + if not node.hidden then + i = i + 1 - if not node.absolute_path or not uv.fs_stat(node.absolute_path) then - break - end - - -- match against node absolute and link, as symlinks themselves will differ - if node.absolute_path == fname_real or node.link_to == fname_real then - return i - end - local abs_match = vim.startswith(fname_real, node.absolute_path .. utils.path_separator) - local link_match = node.link_to and vim.startswith(fname_real, node.link_to .. utils.path_separator) - local path_matches = node.nodes and (abs_match or link_match) - if path_matches then - if not node.open then - node.open = true - tree_altered = true + if not node.absolute_path or not uv.fs_stat(node.absolute_path) then + break end - if #node.nodes == 0 then - core.get_explorer():expand(node) + -- match against node absolute and link, as symlinks themselves will differ + if node.absolute_path == fname_real or node.link_to == fname_real then + return i end + local abs_match = vim.startswith(fname_real, node.absolute_path .. utils.path_separator) + local link_match = node.link_to and vim.startswith(fname_real, node.link_to .. utils.path_separator) + local path_matches = node.nodes and (abs_match or link_match) + if path_matches then + if not node.open then + node.open = true + tree_altered = true + end - if iterate_nodes(node.nodes) ~= nil then - return i + if #node.nodes == 0 then + core.get_explorer():expand(node) + end + + if iterate_nodes(node.nodes) ~= nil then + return i + end + -- mandatory to iterate i + elseif node.open then + iterate_nodes(node.nodes) end - -- mandatory to iterate i - elseif node.open then - iterate_nodes(node.nodes) end end end diff --git a/lua/nvim-tree/actions/init.lua b/lua/nvim-tree/actions/init.lua index ab6065a2fb3..6544a5861e5 100644 --- a/lua/nvim-tree/actions/init.lua +++ b/lua/nvim-tree/actions/init.lua @@ -8,6 +8,7 @@ local nvim_tree_callback = require("nvim-tree.config").nvim_tree_callback local M = { mappings = { + { key = {"m"}, action = "open_popup_menu"}, { key = { "", "o", "<2-LeftMouse>" }, action = "edit" }, { key = "", action = "edit_in_place" }, { key = "O", action = "edit_no_picker" }, @@ -40,6 +41,8 @@ local M = { { key = "]c", action = "next_git_item" }, { key = "-", action = "dir_up" }, { key = "s", action = "system_open" }, + { key = "f", action = "live_filter" }, + { key = "F", action = "clear_live_filter" }, { key = "q", action = "close" }, { key = "g?", action = "toggle_help" }, { key = "W", action = "collapse_all" }, @@ -52,6 +55,7 @@ local M = { } local keypress_funcs = { + open_popup_menu = require("nvim-tree.popup-menu").open_menu, close = view.close, close_node = require("nvim-tree.actions.movements").parent_node(true), collapse_all = require("nvim-tree.actions.collapse-all").fn, @@ -65,6 +69,8 @@ local keypress_funcs = { first_sibling = require("nvim-tree.actions.movements").sibling(-math.huge), full_rename = require("nvim-tree.actions.rename-file").fn(true), last_sibling = require("nvim-tree.actions.movements").sibling(math.huge), + live_filter = require("nvim-tree.live-filter").start_filtering, + clear_live_filter = require("nvim-tree.live-filter").clear_filter, next_git_item = require("nvim-tree.actions.movements").find_git_item "next", next_sibling = require("nvim-tree.actions.movements").sibling(1), parent_node = require("nvim-tree.actions.movements").parent_node(false), @@ -92,6 +98,11 @@ function M.on_keypress(action) if view.is_help_ui() and action ~= "toggle_help" then return end + + if action == "live_filter" or action == "clear_live_filter" then + return keypress_funcs[action]() + end + local node = lib.get_node_at_cursor() if not node then return @@ -184,14 +195,14 @@ local function merge_mappings(user_mappings) if type(map.key) == "table" then local filtered_keys = {} for _, key in pairs(map.key) do - if not vim.tbl_contains(user_keys, key) and not vim.tbl_contains(removed_keys, key) then + if not vim.tbl_contains(user_keys, key:lower()) and not vim.tbl_contains(removed_keys, key:lower()) then table.insert(filtered_keys, key) end end map.key = filtered_keys return not vim.tbl_isempty(map.key) else - return not vim.tbl_contains(user_keys, map.key) and not vim.tbl_contains(removed_keys, map.key) + return not vim.tbl_contains(user_keys, map.key:lower()) and not vim.tbl_contains(removed_keys, map.key:lower()) end end, M.mappings) diff --git a/lua/nvim-tree/actions/movements.lua b/lua/nvim-tree/actions/movements.lua index 49a36c7760b..cc6833059a5 100644 --- a/lua/nvim-tree/actions/movements.lua +++ b/lua/nvim-tree/actions/movements.lua @@ -6,34 +6,25 @@ local lib = require "nvim-tree.lib" local M = {} -local function get_line_from_node(node, find_parent) +local function get_index_of(node, nodes) local node_path = node.absolute_path + local line = 1 - if find_parent then - node_path = node.absolute_path:match("(.*)" .. utils.path_separator) - end - - local line = core.get_nodes_starting_line() - local function iter(nodes, recursive) - for _, _node in ipairs(nodes) do + for _, _node in ipairs(nodes) do + if not _node.hidden then local n = lib.get_last_group_node(_node) if node_path == n.absolute_path then - return line, _node + return line end line = line + 1 - if _node.open == true and recursive then - local _, child = iter(_node.nodes, recursive) - if child ~= nil then - return line, child - end - end end end - return iter end function M.parent_node(should_close) + should_close = should_close or false + return function(node) if should_close and node.open then node.open = false @@ -64,41 +55,26 @@ function M.sibling(direction) return end - local iter = get_line_from_node(node, true) - local node_path = node.absolute_path + local parent = node.parent or core.get_explorer() + local parent_nodes = vim.tbl_filter(function(n) + return not n.hidden + end, parent.nodes) - local line = 0 - local parent, _ + local node_index = get_index_of(node, parent_nodes) - -- Check if current node is already at root nodes - for index, _node in ipairs(core.get_explorer().nodes) do - if node_path == _node.absolute_path then - line = index - end + local target_idx = node_index + direction + if target_idx < 1 then + target_idx = 1 + elseif target_idx > #parent_nodes then + target_idx = #parent_nodes end - if line > 0 then - parent = core.get_explorer() - else - _, parent = iter(core.get_explorer().nodes, true) - if parent ~= nil and #parent.nodes > 1 then - line, _ = get_line_from_node(node)(parent.nodes) - end - - -- Ignore parent line count - line = line - 1 - end - - local index = line + direction - if index < 1 then - index = 1 - elseif index > #parent.nodes then - index = #parent.nodes - end - local target_node = parent.nodes[index] + local target_node = parent_nodes[target_idx] + local _, line = utils.find_node(core.get_explorer().nodes, function(n) + return n.absolute_path == target_node.absolute_path + end) - line, _ = get_line_from_node(target_node)(core.get_explorer().nodes, true) - view.set_cursor { line, 0 } + view.set_cursor { line + 1, 0 } end end diff --git a/lua/nvim-tree/actions/open-file.lua b/lua/nvim-tree/actions/open-file.lua index 9079120cd2e..b2f7315ced2 100644 --- a/lua/nvim-tree/actions/open-file.lua +++ b/lua/nvim-tree/actions/open-file.lua @@ -131,33 +131,7 @@ end local function open_file_in_tab(filename) if M.quit_on_open then view.close() - else - -- Switch window first to ensure new window doesn't inherit settings from - -- NvimTree - if lib.target_winid > 0 and api.nvim_win_is_valid(lib.target_winid) then - api.nvim_set_current_win(lib.target_winid) - else - vim.cmd "wincmd p" - end - end - - -- This sequence of commands are here to ensure a number of things: the new - -- buffer must be opened in the current tabpage first so that focus can be - -- brought back to the tree if it wasn't quit_on_open. It also ensures that - -- when we open the new tabpage with the file, its window doesn't inherit - -- settings from NvimTree, as it was already loaded. - - vim.cmd("edit " .. vim.fn.fnameescape(filename)) - - local alt_bufid = vim.fn.bufnr "#" - if alt_bufid ~= -1 then - api.nvim_set_current_buf(alt_bufid) end - - if not M.quit_on_open then - vim.cmd "wincmd p" - end - vim.cmd("tabe " .. vim.fn.fnameescape(filename)) end diff --git a/lua/nvim-tree/colors.lua b/lua/nvim-tree/colors.lua index 9d361952cc2..fb45561485e 100644 --- a/lua/nvim-tree/colors.lua +++ b/lua/nvim-tree/colors.lua @@ -52,6 +52,8 @@ local function get_hl_groups() GitNew = { fg = colors.yellow }, WindowPicker = { gui = "bold", fg = "#ededed", bg = "#4493c8" }, + LiveFilterPrefix = { gui = "bold", fg = colors.purple }, + LiveFilterValue = { gui = "bold", fg = "#fff" }, } end diff --git a/lua/nvim-tree/core.lua b/lua/nvim-tree/core.lua index bc05743970c..7ee7eba62d1 100644 --- a/lua/nvim-tree/core.lua +++ b/lua/nvim-tree/core.lua @@ -1,5 +1,6 @@ local events = require "nvim-tree.events" local explorer = require "nvim-tree.explorer" +local live_filter = require "nvim-tree.live-filter" local view = require "nvim-tree.view" local M = {} @@ -28,6 +29,9 @@ function M.get_nodes_starting_line() if view.is_root_folder_visible(M.get_cwd()) then offset = offset + 1 end + if live_filter.filter then + return offset + 1 + end return offset end diff --git a/lua/nvim-tree/diagnostics.lua b/lua/nvim-tree/diagnostics.lua index b03b47207d7..685a1c85196 100644 --- a/lua/nvim-tree/diagnostics.lua +++ b/lua/nvim-tree/diagnostics.lua @@ -32,7 +32,7 @@ local function add_sign(linenr, severity) return end local sign_name = sign_names[severity][1] - vim.fn.sign_place(1, GROUP, sign_name, buf, { lnum = linenr }) + vim.fn.sign_place(0, GROUP, sign_name, buf, { lnum = linenr, priority = 2 }) end local function from_nvim_lsp() diff --git a/lua/nvim-tree/explorer/explore.lua b/lua/nvim-tree/explorer/explore.lua index 5b6a294da8d..70aa93c12ad 100644 --- a/lua/nvim-tree/explorer/explore.lua +++ b/lua/nvim-tree/explorer/explore.lua @@ -6,6 +6,7 @@ local builders = require "nvim-tree.explorer.node-builders" local common = require "nvim-tree.explorer.common" local sorters = require "nvim-tree.explorer.sorters" local filters = require "nvim-tree.explorer.filters" +local live_filter = require "nvim-tree.live-filter" local M = {} @@ -76,6 +77,7 @@ function M.explore(node, status) end sorters.merge_sort(node.nodes, sorters.node_comparator) + live_filter.apply_filter(node) return node.nodes end diff --git a/lua/nvim-tree/explorer/reload.lua b/lua/nvim-tree/explorer/reload.lua index f12ff05e2fb..6291e1e4939 100644 --- a/lua/nvim-tree/explorer/reload.lua +++ b/lua/nvim-tree/explorer/reload.lua @@ -6,6 +6,7 @@ local builders = require "nvim-tree.explorer.node-builders" local common = require "nvim-tree.explorer.common" local filters = require "nvim-tree.explorer.filters" local sorters = require "nvim-tree.explorer.sorters" +local live_filter = require "nvim-tree.live-filter" local M = {} @@ -77,6 +78,7 @@ function M.reload(node, status) end sorters.merge_sort(node.nodes, sorters.node_comparator) + live_filter.apply_filter(node) return node.nodes end diff --git a/lua/nvim-tree/explorer/sorters.lua b/lua/nvim-tree/explorer/sorters.lua index e82cba0061c..4168a931c95 100644 --- a/lua/nvim-tree/explorer/sorters.lua +++ b/lua/nvim-tree/explorer/sorters.lua @@ -124,12 +124,38 @@ function M.node_comparator_modification_time(a, b) return last_modified_b <= last_modified_a end +function M.node_comparator_extension(a, b) + if not (a and b) then + return true + end + + if a.nodes and not b.nodes then + return true + elseif not a.nodes and b.nodes then + return false + end + + if not (a.extension and b.extension) then + return true + end + + if a.extension and not b.extension then + return true + elseif not a.extension and b.extension then + return false + end + + return a.extension:lower() <= b.extension:lower() +end + function M.setup(opts) M.sort_by = opts.sort_by if M.sort_by == "modification_time" then M.node_comparator = M.node_comparator_modification_time elseif M.sort_by == "case_sensitive" then M.node_comparator = M.node_comparator_name_case_sensisive + elseif M.sort_by == "extension" then + M.node_comparator = M.node_comparator_extension else M.node_comparator = M.node_comparator_name_ignorecase end diff --git a/lua/nvim-tree/lib.lua b/lua/nvim-tree/lib.lua index 649a468bbc3..cf768170a61 100644 --- a/lua/nvim-tree/lib.lua +++ b/lua/nvim-tree/lib.lua @@ -13,23 +13,25 @@ function M.get_node_at_cursor() if not core.get_explorer() then return end + local winnr = view.get_winnr() if not winnr then return end + local cursor = api.nvim_win_get_cursor(view.get_winnr()) local line = cursor[1] if view.is_help_ui() then local help_lines = require("nvim-tree.renderer.help").compute_lines() local help_text = utils.get_nodes_by_line(help_lines, 1)[line] return { name = help_text } - else - if line == 1 and core.get_explorer().cwd ~= "/" and view.is_root_folder_visible() then - return { name = ".." } - end + end - return utils.get_nodes_by_line(core.get_explorer().nodes, core.get_nodes_starting_line())[line] + if line == 1 and view.is_root_folder_visible(core.get_cwd()) then + return { name = ".." } end + + return utils.get_nodes_by_line(core.get_explorer().nodes, core.get_nodes_starting_line())[line] end -- If node is grouped, return the last node in the group. Otherwise, return the given node. diff --git a/lua/nvim-tree/live-filter.lua b/lua/nvim-tree/live-filter.lua new file mode 100644 index 00000000000..7fa8c5f089d --- /dev/null +++ b/lua/nvim-tree/live-filter.lua @@ -0,0 +1,132 @@ +local a = vim.api + +local view = require "nvim-tree.view" + +local M = { + filter = nil, +} + +local function redraw() + require("nvim-tree.renderer").draw() +end + +local function reset_filter(node_) + local function iterate(n) + n.hidden = false + if n.nodes then + for _, node in pairs(n.nodes) do + iterate(node) + end + end + end + iterate(node_ or TreeExplorer) +end + +local overlay_bufnr = nil +local overlay_winnr = nil + +local function remove_overlay() + a.nvim_win_close(overlay_winnr, { force = true }) + overlay_bufnr = nil + overlay_winnr = nil + + if M.filter == "" then + M.clear_filter() + end +end + +local function matches(node) + local path = node.cwd or node.absolute_path + local name = vim.fn.fnamemodify(path, ":t") + return vim.regex(M.filter):match_str(name) ~= nil +end + +function M.apply_filter(node_) + if not M.filter or M.filter == "" then + reset_filter(node_) + return + end + + local function iterate(node) + local filtered_nodes = 0 + local nodes = node.group_next and { node.group_next } or node.nodes + + if nodes then + for _, n in pairs(nodes) do + iterate(n) + if n.hidden then + filtered_nodes = filtered_nodes + 1 + end + end + end + + local has_nodes = nodes and (M.always_show_folders or #nodes > filtered_nodes) + node.hidden = not (has_nodes or matches(node)) + end + + iterate(node_ or TreeExplorer) +end + +local function record_char() + vim.schedule(function() + M.filter = a.nvim_buf_get_lines(overlay_bufnr, 0, -1, false)[1] + M.apply_filter() + redraw() + end) +end + +local function configure_buffer_overlay() + overlay_bufnr = a.nvim_create_buf(false, true) + + a.nvim_buf_attach(overlay_bufnr, true, { + on_lines = record_char, + }) + + a.nvim_create_autocmd("InsertLeave", { + callback = remove_overlay, + once = true, + }) + + a.nvim_buf_set_keymap(overlay_bufnr, "i", "", "stopinsert", {}) +end + +local function create_overlay() + configure_buffer_overlay() + overlay_winnr = a.nvim_open_win(overlay_bufnr, true, { + col = 1, + row = 0, + relative = "cursor", + width = math.max(20, a.nvim_win_get_width(view.get_winnr()) - #M.prefix - 2), + height = 1, + border = "none", + style = "minimal", + }) + a.nvim_buf_set_option(overlay_bufnr, "modifiable", true) + a.nvim_buf_set_lines(overlay_bufnr, 0, -1, false, { M.filter }) + vim.cmd "startinsert" + a.nvim_win_set_cursor(overlay_winnr, { 1, #M.filter + 1 }) +end + +function M.start_filtering() + M.filter = M.filter or "" + + redraw() + local row = require("nvim-tree.core").get_nodes_starting_line() - 1 + local col = #M.prefix > 0 and #M.prefix - 1 or 1 + view.set_cursor { row, col } + -- needs scheduling to let the cursor move before initializing the window + vim.schedule(create_overlay) +end + +function M.clear_filter() + M.filter = nil + reset_filter() + redraw() +end + +function M.setup(opts) + M.prefix = opts.live_filter.prefix + M.always_show_folders = opts.live_filter.always_show_folders +end + +return M diff --git a/lua/nvim-tree/popup-menu/init.lua b/lua/nvim-tree/popup-menu/init.lua new file mode 100644 index 00000000000..9d380cfb045 --- /dev/null +++ b/lua/nvim-tree/popup-menu/init.lua @@ -0,0 +1,112 @@ +local a = vim.api + +local get_node = require('nvim-tree.lib').get_node_at_cursor +local get_explorer = require('nvim-tree.core').get_explorer + +local M = {} + +M.is_open = false +M.win = 0 +M.bufnr = 0 + +local actions = { + ['copy'] = require('nvim-tree.actions.copy-paste').copy +} + +M.mappings = { + [''] = 'close_menu', + [''] = 'on_selection', +} + +local ns_PopupMenu = a.nvim_create_namespace('ns_NvimTreePopupMenu') + +local function create_buf() + if vim.fn.bufexists("NvimTreePopupMenuBuf") == 1 then + a.nvim_buf_delete(vim.fn.bufnr('NvimTreePopupMenuBuf'), {} ) + end + local buf = a.nvim_create_buf(false, true) + a.nvim_buf_set_name(buf, 'NvimTreePopupMenuBuf') + M.bufnr = buf + + return buf +end + +function M.open_menu() + if M.is_open == true then + close_menu() + end + + create_buf() + local win_opts = { + width = 10, -- we should set this as NvimExplorer width + height = 1, -- TODO: Set this as length of actions, as for now I'm not able to do it. + row = 1, + col = 0, + style = 'minimal', + relative = 'cursor' + } + + local win_ui = a.nvim_open_win(M.bufnr, true, win_opts) + M.is_open = true + M.win = win_ui + set_actions(actions) + + -- TODO: Convert this to nvim lua api. + -- at this time on my machine with nvim 0.7.0-dev+1328-gfb5587d2b + -- keep yelling that "event" must be an array or string + local au_group = a.nvim_create_augroup('NvimSelectionAuGroup', { clear = true }) + vim.cmd(string.format([[ + augroup NvimSelectionAuGroup + au! CursorMoved :lua require('nvim-tree.popup-menu').add_hl_to_selection() + augroup END + ]], M.bufnr)) + + -- mappings on open window + -- should we pass this on separate file? + for k, v in pairs(M.mappings) do + if v ~= nil then + a.nvim_buf_set_keymap( + M.bufnr, + 'n', k, + string.format([[:lua %s()]], v), { noremap = true, silent = true }) + end + end + end + +function close_menu() + a.nvim_win_close(M.win, true) + M.is_open = false +end + +function set_actions(tbl) + a.nvim_buf_set_lines(M.bufnr, 0, 1, true, vim.tbl_keys(tbl)) +end + +function M.add_hl_to_selection() + if M.is_open == true then + local row = a.nvim_win_get_cursor(M.win)[1] + local sel_item = a.nvim_buf_get_lines(M.bufnr, row -1, row, {})[1] -- should we pass this as module params to let user customize action on current selected item? + + -- clear prev highlights + a.nvim_buf_clear_namespace(M.bufnr, ns_PopupMenu, 0, -1) + + a.nvim_buf_add_highlight( + M.bufnr, + ns_PopupMenu, + 'Error', + row -1, + 0, + -1 + ) + end +end + +function on_selection() + local row = a.nvim_win_get_cursor(M.win)[1] + local sel_item = a.nvim_buf_get_lines(M.bufnr, row -1, row, {})[1] -- should we pass this as module params to let user customize action on current selected item? + + actions[sel_item](get_node()) + close_menu() +end + +return M diff --git a/lua/nvim-tree/popup-menu/mappings.lua b/lua/nvim-tree/popup-menu/mappings.lua new file mode 100644 index 00000000000..6784360b8d4 --- /dev/null +++ b/lua/nvim-tree/popup-menu/mappings.lua @@ -0,0 +1,17 @@ +local a = vim.api + +local M = {} + +M.mappings = { + [''] = require("nvim-tree.popup-menu").test +} + +for k, v in pairs(M.mappings) do + if M.bufnr ~= 0 or nil then + a.nvim_buf_set_keymap( + M.bufnr, + 'n', k, + string.format([[:lua %s]], v), { noremap = true, silent = true }) + end +end +return M diff --git a/lua/nvim-tree/popup-menu/scratch.lua b/lua/nvim-tree/popup-menu/scratch.lua new file mode 100644 index 00000000000..2736ac4f828 --- /dev/null +++ b/lua/nvim-tree/popup-menu/scratch.lua @@ -0,0 +1,7 @@ +function t() + for _,v in ipairs(vim.api.nvim_list_bufs()) do + if vim.api.nvim_buf_get_name(v):match 'NvimTree' ~= nil then + print('found!', v) + end + end +end diff --git a/lua/nvim-tree/renderer/builder.lua b/lua/nvim-tree/renderer/builder.lua index 38a7191f5d1..b583cda82c9 100644 --- a/lua/nvim-tree/renderer/builder.lua +++ b/lua/nvim-tree/renderer/builder.lua @@ -14,6 +14,7 @@ function Builder.new(root_cwd) highlights = {}, lines = {}, markers = {}, + signs = {}, root_cwd = root_cwd, }, Builder) end @@ -43,6 +44,12 @@ function Builder:configure_picture_map(picture_map) return self end +function Builder:configure_filter(filter, prefix) + self.filter_prefix = prefix + self.filter = filter + return self +end + function Builder:configure_opened_file_highlighting(level) if level == 1 then self.open_file_highlight = "icon" @@ -61,9 +68,11 @@ function Builder:configure_git_icons_padding(padding) end function Builder:configure_git_icons_placement(where) - where = where or "before" - self.is_git_before = where == "before" - self.is_git_after = not self.is_git_before + if where == "signcolumn" then + vim.fn.sign_unplace(git.SIGN_GROUP) + self.is_git_sign = true + end + self.is_git_after = where == "after" and not self.is_git_sign return self end @@ -91,10 +100,11 @@ function Builder:_unwrap_git_data(git_icons_and_hl_groups, offset) end local icon = "" - for _, v in ipairs(git_icons_and_hl_groups) do + for i, v in ipairs(git_icons_and_hl_groups) do if #v.icon > 0 then self:_insert_highlight(v.hl, offset + #icon, offset + #icon + #v.icon) - icon = icon .. v.icon + local remove_padding = self.is_git_after and i == #git_icons_and_hl_groups + icon = icon .. v.icon .. (remove_padding and "" or self.git_icon_padding) end end return icon @@ -109,7 +119,7 @@ function Builder:_build_folder(node, padding, git_hl, git_icons_tbl) local foldername = name .. self.trailing_slash local git_icons = self:_unwrap_git_data(git_icons_tbl, offset + #icon + (self.is_git_after and #foldername + 1 or 0)) - local fname_starts_at = offset + #icon + (self.is_git_before and #git_icons or 0) + local fname_starts_at = offset + #icon + (self.is_git_after and 0 or #git_icons) local line = self:_format_line(padding .. icon, foldername, git_icons) self:_insert_line(line) @@ -134,12 +144,13 @@ function Builder:_build_folder(node, padding, git_hl, git_icons_tbl) end function Builder:_format_line(before, after, git_icons) + git_icons = self.is_git_after and git_icons and " " .. git_icons or git_icons return string.format( "%s%s%s%s", before, - #git_icons > 0 and not self.is_git_after and git_icons .. self.git_icon_padding or "", + self.is_git_after and "" or git_icons, after, - #git_icons > 0 and self.is_git_after and self.git_icon_padding .. git_icons or "" + self.is_git_after and git_icons or "" ) end @@ -216,8 +227,8 @@ function Builder:_build_file(node, padding, git_highlight, git_icons_tbl) end end -function Builder:_build_line(tree, node, idx) - local padding = pad.get_padding(self.depth, idx, tree, node, self.markers) +function Builder:_build_line(node, idx, num_children) + local padding = pad.get_padding(self.depth, idx, num_children, node, self.markers) if self.depth > 0 then self:_insert_highlight("NvimTreeIndentMarker", 0, string.len(padding)) @@ -226,6 +237,12 @@ function Builder:_build_line(tree, node, idx) local git_highlight = git.get_highlight(node) local git_icons_tbl = git.get_icons(node) + if self.is_git_sign and git_icons_tbl and #git_icons_tbl > 0 then + local git_info = git_icons_tbl[1] + table.insert(self.signs, { sign = git_info.hl, lnum = self.index + 1 }) + git_icons_tbl = {} + end + local is_folder = node.nodes ~= nil local is_symlink = node.link_to ~= nil @@ -245,9 +262,28 @@ function Builder:_build_line(tree, node, idx) end end +function Builder:_get_nodes_number(nodes) + if not self.filter then + return #nodes + end + + local i = 0 + for _, n in pairs(nodes) do + if not n.hidden then + i = i + 1 + end + end + return i +end + function Builder:build(tree) - for idx, node in ipairs(tree.nodes) do - self:_build_line(tree, node, idx) + local num_children = self:_get_nodes_number(tree.nodes) + local idx = 1 + for _, node in ipairs(tree.nodes) do + if not node.hidden then + self:_build_line(node, idx, num_children) + idx = idx + 1 + end end return self @@ -266,11 +302,20 @@ function Builder:build_header(show_header) self.index = 1 end + if self.filter then + local filter_line = self.filter_prefix .. "/" .. self.filter .. "/" + self:_insert_line(filter_line) + local prefix_length = string.len(self.filter_prefix) + self:_insert_highlight("NvimTreeLiveFilterPrefix", 0, prefix_length) + self:_insert_highlight("NvimTreeLiveFilterValue", prefix_length, string.len(filter_line)) + self.index = self.index + 1 + end + return self end function Builder:unwrap() - return self.lines, self.highlights + return self.lines, self.highlights, self.signs end return Builder diff --git a/lua/nvim-tree/renderer/components/git.lua b/lua/nvim-tree/renderer/components/git.lua index 495a77f6d0a..2d0d5b2d73a 100644 --- a/lua/nvim-tree/renderer/components/git.lua +++ b/lua/nvim-tree/renderer/components/git.lua @@ -1,7 +1,9 @@ local _icons = require "nvim-tree.renderer.icon-config" local utils = require "nvim-tree.utils" -local M = {} +local M = { + SIGN_GROUP = "NvimTreeGitSigns", +} local function build_icons_table() local i = M.icon_state.icons.git_icons @@ -124,6 +126,17 @@ local git_hl = { [" A"] = "none", } +function M.setup_signs() + local i = M.icon_state.icons.git_icons + vim.fn.sign_define("NvimTreeGitDirty", { text = i.unstaged, texthl = "NvimTreeGitDirty" }) + vim.fn.sign_define("NvimTreeGitStaged", { text = i.staged, texthl = "NvimTreeGitStaged" }) + vim.fn.sign_define("NvimTreeGitMerge", { text = i.unmerged, texthl = "NvimTreeGitMerge" }) + vim.fn.sign_define("NvimTreeGitRenamed", { text = i.renamed, texthl = "NvimTreeGitRenamed" }) + vim.fn.sign_define("NvimTreeGitNew", { text = i.untracked, texthl = "NvimTreeGitNew" }) + vim.fn.sign_define("NvimTreeGitDeleted", { text = i.deleted, texthl = "NvimTreeGitDeleted" }) + vim.fn.sign_define("NvimTreeGitIgnored", { text = i.ignored, texthl = "NvimTreeGitIgnored" }) +end + local function get_highlight_(node) local git_status = node.git_status if not git_status then diff --git a/lua/nvim-tree/renderer/components/padding.lua b/lua/nvim-tree/renderer/components/padding.lua index 50375cc4a5c..d455859b1d7 100644 --- a/lua/nvim-tree/renderer/components/padding.lua +++ b/lua/nvim-tree/renderer/components/padding.lua @@ -14,13 +14,13 @@ local function get_padding_arrows(icon_state) end end -local function get_padding_indent_markers(depth, idx, tree, _, markers) +local function get_padding_indent_markers(depth, idx, nodes_number, _, markers) local padding = "" if depth ~= 0 then local rdepth = depth / 2 - markers[rdepth] = idx ~= #tree.nodes + markers[rdepth] = idx ~= nodes_number for i = 1, rdepth do - if idx == #tree.nodes and i == rdepth then + if idx == nodes_number and i == rdepth then padding = padding .. M.config.indent_markers.icons.corner elseif markers[i] then padding = padding .. M.config.indent_markers.icons.edge diff --git a/lua/nvim-tree/renderer/init.lua b/lua/nvim-tree/renderer/init.lua index 6ae44b87143..be6917dcc25 100644 --- a/lua/nvim-tree/renderer/init.lua +++ b/lua/nvim-tree/renderer/init.lua @@ -8,6 +8,7 @@ local icon_component = require "nvim-tree.renderer.components.icons" local help = require "nvim-tree.renderer.help" local git = require "nvim-tree.renderer.components.git" local Builder = require "nvim-tree.renderer.builder" +local live_filter = require "nvim-tree.live-filter" local api = vim.api @@ -17,11 +18,14 @@ local M = { local namespace_id = api.nvim_create_namespace "NvimTreeHighlights" -local function _draw(bufnr, lines, hl) +local function _draw(bufnr, lines, hl, signs) api.nvim_buf_set_option(bufnr, "modifiable", true) api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) M.render_hl(bufnr, hl) api.nvim_buf_set_option(bufnr, "modifiable", false) + for _, sign in pairs(signs) do + vim.fn.sign_place(0, git.SIGN_GROUP, sign.sign, bufnr, { lnum = sign.lnum, priority = 1 }) + end end function M.render_hl(bufnr, hl) @@ -71,10 +75,11 @@ function M.draw() git.reload() local lines, hl + local signs = {} if view.is_help_ui() then lines, hl = help.compute_lines() else - lines, hl = Builder.new(core.get_cwd()) + lines, hl, signs = Builder.new(core.get_cwd()) :configure_initial_depth(should_show_arrows()) :configure_root_modifier(vim.g.nvim_tree_root_folder_modifier) :configure_trailing_slash(vim.g.nvim_tree_add_trailing == 1) @@ -83,12 +88,14 @@ function M.draw() :configure_opened_file_highlighting(vim.g.nvim_tree_highlight_opened_files) :configure_git_icons_padding(vim.g.nvim_tree_icon_padding) :configure_git_icons_placement(M.config.icons.git_placement) + :configure_filter(live_filter.filter, live_filter.prefix) :build_header(view.is_root_folder_visible(core.get_cwd())) :build(core.get_explorer()) :unwrap() end - _draw(bufnr, lines, hl) + _draw(bufnr, lines, hl, signs) + M.last_highlights = hl if cursor and #lines >= cursor[1] then @@ -111,6 +118,7 @@ function M.setup(opts) } _padding.setup(opts) + git.setup_signs() end return M diff --git a/lua/nvim-tree/utils.lua b/lua/nvim-tree/utils.lua index 017c5765c22..d0ddf2d281b 100644 --- a/lua/nvim-tree/utils.lua +++ b/lua/nvim-tree/utils.lua @@ -103,23 +103,26 @@ function M.find_node(nodes, fn) local function iter(nodes_, fn_) local i = 1 for _, node in ipairs(nodes_) do - if fn_(node) then - return node, i - end - if node.open and #node.nodes > 0 then - local n, idx = iter(node.nodes, fn_) - i = i + idx - if n then - return n, i + if not node.hidden then + if fn_(node) then + return node, i + end + if node.open and #node.nodes > 0 then + local n, idx = iter(node.nodes, fn_) + i = i + idx + if n then + return n, i + end + else + i = i + 1 end - else - i = i + 1 end end return nil, i end local node, i = iter(nodes, fn) - i = require("nvim-tree.view").View.hide_root_folder and i - 1 or i + i = require("nvim-tree.view").is_root_folder_visible() and i or i - 1 + i = require("nvim-tree.live-filter").filter and i + 1 or i return node, i end @@ -132,12 +135,14 @@ function M.get_nodes_by_line(nodes_all, line_start) local line = line_start local function iter(nodes) for _, node in ipairs(nodes) do - nodes_by_line[line] = node - line = line + 1 - if node.open == true then - local child = iter(node.nodes) - if child ~= nil then - return child + if not node.hidden then + nodes_by_line[line] = node + line = line + 1 + if node.open == true then + local child = iter(node.nodes) + if child ~= nil then + return child + end end end end diff --git a/lua/nvim-tree/view.lua b/lua/nvim-tree/view.lua index 8daeba0e6c7..be972adf33a 100644 --- a/lua/nvim-tree/view.lua +++ b/lua/nvim-tree/view.lua @@ -108,38 +108,26 @@ local move_tbl = { top = "K", } --- TODO: remove this once they fix https://github.com/neovim/neovim/issues/14670 -local function set_local(opt, value) - local cmd - if value == true then - cmd = string.format("setlocal %s", opt) - elseif value == false then - cmd = string.format("setlocal no%s", opt) - else - cmd = string.format("setlocal %s=%s", opt, value) - end - vim.cmd(cmd) -end - -- setup_tabpage sets up the initial state of a tab local function setup_tabpage(tabpage) local winnr = a.nvim_get_current_win() M.View.tabpages[tabpage] = vim.tbl_extend("force", M.View.tabpages[tabpage] or tabinitial, { winnr = winnr }) end -local function open_window() - a.nvim_command "vsp" - M.reposition_window() - setup_tabpage(a.nvim_get_current_tabpage()) -end - local function set_window_options_and_buffer() pcall(vim.cmd, "buffer " .. M.get_bufnr()) for k, v in pairs(M.View.winopts) do - set_local(k, v) + vim.opt_local[k] = v end end +local function open_window() + a.nvim_command "vsp" + M.reposition_window() + setup_tabpage(a.nvim_get_current_tabpage()) + set_window_options_and_buffer() +end + local function get_existing_buffers() return vim.tbl_filter(function(buf) return a.nvim_buf_is_valid(buf) and vim.fn.buflisted(buf) == 1 @@ -190,7 +178,6 @@ function M.open(options) create_buffer() open_window() - set_window_options_and_buffer() M.resize() local opts = options or { focus_tree = true } @@ -267,7 +254,7 @@ end function M.is_visible(opts) if opts and opts.any_tabpage then for _, v in pairs(M.View.tabpages) do - if a.nvim_win_is_valid(v.winnr) then + if v.winnr and a.nvim_win_is_valid(v.winnr) then return true end end