From 1dfd894ce9c4e6f3eb91feeac3b7fa7eb333c1e4 Mon Sep 17 00:00:00 2001 From: Antonin Godard Date: Sun, 3 Dec 2023 12:01:54 -0800 Subject: [PATCH 1/7] feat(#1389): add next recursive for git and diag moves The recurse opt can be used to directly go to the next item showing git/diagnostic status recursively. Signed-off-by: Antonin Godard --- doc/nvim-tree-lua.txt | 11 ++ lua/nvim-tree/actions/moves/item.lua | 184 +++++++++++++++++++++------ lua/nvim-tree/api.lua | 2 + 3 files changed, 156 insertions(+), 41 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index e3923baf021..c656b7c3751 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -1875,6 +1875,11 @@ node.open.preview_no_picker() *nvim-tree-api.node.open.preview_no_picker()* node.navigate.git.next() *nvim-tree-api.node.navigate.git.next()* Navigate to the next item showing git status. + *nvim-tree-api.node.navigate.git.next_recursive()* +node.navigate.git.next_recursive() + Same as |node.navigate.git.next()|, but navigates to next item showing git + status recursively. Needs `git.show_on_dirs` set to `true`. + *nvim-tree-api.node.navigate.git.next_skip_gitignored()* node.navigate.git.next_skip_gitignored() Same as |node.navigate.git.next()|, but skips gitignored files. @@ -1890,6 +1895,12 @@ node.navigate.git.prev_skip_gitignored() node.navigate.diagnostics.next() Navigate to the next item showing diagnostic status. + *nvim-tree-api.node.navigate.diagnostics.next_recursive()* +node.navigate.diagnostics.next_recursive() + Same as |node.navigate.diagnostics.next()|, but navigates to next item + showing diagnostic status recursively. Needs `diagnostics.show_on_dirs` + and `diagnostics.show_on_open_dirs` set to `true`. + *nvim-tree-api.node.navigate.diagnostics.prev()* node.navigate.diagnostics.prev() Navigate to the next item showing diagnostic status. diff --git a/lua/nvim-tree/actions/moves/item.lua b/lua/nvim-tree/actions/moves/item.lua index bf72c0ea2df..bc8fdb46d7b 100644 --- a/lua/nvim-tree/actions/moves/item.lua +++ b/lua/nvim-tree/actions/moves/item.lua @@ -6,6 +6,132 @@ local explorer_node = require "nvim-tree.explorer.node" local diagnostics = require "nvim-tree.diagnostics" local M = {} +local MAX_DEPTH = 100 + +---Return the status of the node or nil if no status, depending on the type of +---status. +---@param node table node to inspect +---@param what string type of status +---@return any|nil +local function get_status(node, what) + if what == "git" then + return explorer_node.get_git_status(node) + elseif what == "diag" then + return node.diag_status + elseif what == "opened" then + local opened_nb = vim.fn.bufloaded(node.absolute_path) + if opened_nb == 0 then + return nil + else + return opened_nb + end + end + + return nil +end + +---Move to the next node that has a valid status. If none found, don't move. +---@param where string where to move (forwards or backwards) +---@param what string type of status +---@param skip_gitignored boolean default false +local function move(where, what, skip_gitignored) + local node_cur = lib.get_node_at_cursor() + local first_node_line = core.get_nodes_starting_line() + local nodes_by_line = utils.get_nodes_by_line(core.get_explorer().nodes, first_node_line) + local iter_start, iter_end, iter_step, cur, first, nex + + if where == "next" then + iter_start, iter_end, iter_step = first_node_line, #nodes_by_line, 1 + elseif where == "prev" then + iter_start, iter_end, iter_step = #nodes_by_line, first_node_line, -1 + end + + for line = iter_start, iter_end, iter_step do + local node = nodes_by_line[line] + local valid = false + + if what == "git" then + local git_status = explorer_node.get_git_status(node) + valid = git_status ~= nil and (not skip_gitignored or git_status[1] ~= "!!") + elseif what == "diag" then + local diag_status = diagnostics.get_diag_status(node) + valid = diag_status ~= nil and diag_status.value ~= nil + elseif what == "opened" then + valid = vim.fn.bufloaded(node.absolute_path) ~= 0 + end + + if not first and valid then + first = line + end + + if node == node_cur then + cur = line + elseif valid and cur then + nex = line + break + end + end + + if nex then + view.set_cursor { nex, 0 } + elseif vim.o.wrapscan and first then + view.set_cursor { first, 0 } + end +end + +---@param opts NavigationItemOpts +---@param skip_gitignored boolean default false +local function move_next_recursive(opts, skip_gitignored) + -- If the current node: + -- * is a directory + -- * and has a git/diag status + -- * and is not opened + -- expand it. + local node_init = lib.get_node_at_cursor() + if not node_init then + return + end + local status = get_status(node_init, opts.what) + if node_init.nodes ~= nil and status ~= nil and not node_init.open then + lib.expand_or_collapse(node_init) + end + + move(opts.where, opts.what, skip_gitignored) + + local node_cur = lib.get_node_at_cursor() + if not node_cur then + return + end + + -- If we haven't moved at all at this point, return. + if node_init == node_cur then + return + end + + -- i is used to limit iterations. + local i = 0 + local is_dir = node_cur.nodes ~= nil + while is_dir and i < MAX_DEPTH do + if not node_cur.open then + -- Expand the node. + -- Should never collapse since we checked open. + lib.expand_or_collapse(node_cur) + end + + move(opts.where, opts.what, skip_gitignored) + + -- Save current node. + node_cur = lib.get_node_at_cursor() + -- Update is_dir. + if node_cur then + is_dir = node_cur.nodes ~= nil + else + is_dir = false + end + + i = i + 1 + end +end ---@class NavigationItemOpts ---@field where string @@ -15,48 +141,24 @@ local M = {} ---@return fun() function M.fn(opts) return function() - local node_cur = lib.get_node_at_cursor() - local first_node_line = core.get_nodes_starting_line() - local nodes_by_line = utils.get_nodes_by_line(core.get_explorer().nodes, first_node_line) - local iter_start, iter_end, iter_step, cur, first, nex - - if opts.where == "next" then - iter_start, iter_end, iter_step = first_node_line, #nodes_by_line, 1 - elseif opts.where == "prev" then - iter_start, iter_end, iter_step = #nodes_by_line, first_node_line, -1 - end - - for line = iter_start, iter_end, iter_step do - local node = nodes_by_line[line] - local valid = false - - if opts.what == "git" then - local git_status = explorer_node.get_git_status(node) - valid = git_status ~= nil and (not opts.skip_gitignored or git_status[1] ~= "!!") - elseif opts.what == "diag" then - local diag_status = diagnostics.get_diag_status(node) - valid = diag_status ~= nil and diag_status.value ~= nil - elseif opts.what == "opened" then - valid = vim.fn.bufloaded(node.absolute_path) ~= 0 - end - - if not first and valid then - first = line - end - - if node == node_cur then - cur = line - elseif valid and cur then - nex = line - break - end - end - - if nex then - view.set_cursor { nex, 0 } - elseif vim.o.wrapscan and first then - view.set_cursor { first, 0 } + local recurse = false + local skip_gitignored = false + + -- recurse only available for "next" git and diag moves. + if opts.where == "next" and (opts.what == "git" or opts.what == "diag") and opts.recurse ~= nil then + recurse = opts.recurse end + + if opts.skip_gitignored ~= nil then + skip_gitignored = opts.skip_gitignored + end + + if not recurse then + move(opts.where, opts.what, skip_gitignored) + return + end + + move_next_recursive(opts, skip_gitignored) end end diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index 3c78b18d837..c7be8cee93d 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -210,9 +210,11 @@ 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.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.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" }) From 74f73b59e27f23181b5e46aafd2e903b1a476b58 Mon Sep 17 00:00:00 2001 From: Antonin Godard Date: Sun, 31 Dec 2023 13:53:03 -0800 Subject: [PATCH 2/7] refactor: status logic in single function Rename get_status to status_is_valid. Use status_is_valid function in multiple place to avoid duplicating code. Signed-off-by: Antonin Godard --- lua/nvim-tree/actions/moves/item.lua | 36 ++++++++++------------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/lua/nvim-tree/actions/moves/item.lua b/lua/nvim-tree/actions/moves/item.lua index bc8fdb46d7b..12a8eb3dba1 100644 --- a/lua/nvim-tree/actions/moves/item.lua +++ b/lua/nvim-tree/actions/moves/item.lua @@ -12,22 +12,20 @@ local MAX_DEPTH = 100 ---status. ---@param node table node to inspect ---@param what string type of status ----@return any|nil -local function get_status(node, what) +---@param skip_gitignored boolean default false +---@return boolean +local function status_is_valid(node, what, skip_gitignored) if what == "git" then - return explorer_node.get_git_status(node) + local git_status = explorer_node.get_git_status(node) + return git_status ~= nil and (not skip_gitignored or git_status[1] ~= "!!") elseif what == "diag" then - return node.diag_status + local diag_status = diagnostics.get_diag_status(node) + return diag_status ~= nil and diag_status.value ~= nil elseif what == "opened" then - local opened_nb = vim.fn.bufloaded(node.absolute_path) - if opened_nb == 0 then - return nil - else - return opened_nb - end + return vim.fn.bufloaded(node.absolute_path) ~= 0 end - return nil + return false end ---Move to the next node that has a valid status. If none found, don't move. @@ -48,17 +46,7 @@ local function move(where, what, skip_gitignored) for line = iter_start, iter_end, iter_step do local node = nodes_by_line[line] - local valid = false - - if what == "git" then - local git_status = explorer_node.get_git_status(node) - valid = git_status ~= nil and (not skip_gitignored or git_status[1] ~= "!!") - elseif what == "diag" then - local diag_status = diagnostics.get_diag_status(node) - valid = diag_status ~= nil and diag_status.value ~= nil - elseif what == "opened" then - valid = vim.fn.bufloaded(node.absolute_path) ~= 0 - end + local valid = status_is_valid(node, what, skip_gitignored) if not first and valid then first = line @@ -91,8 +79,8 @@ local function move_next_recursive(opts, skip_gitignored) if not node_init then return end - local status = get_status(node_init, opts.what) - if node_init.nodes ~= nil and status ~= nil and not node_init.open then + local valid = status_is_valid(node_init, opts.what, skip_gitignored) + if node_init.nodes ~= nil and valid and not node_init.open then lib.expand_or_collapse(node_init) end From 9e90d3ae9708bef8d58254a035a321f094dd200d Mon Sep 17 00:00:00 2001 From: Antonin Godard Date: Sun, 3 Dec 2023 12:01:54 -0800 Subject: [PATCH 3/7] feat(#1389): add prev recursive for git and diag moves Signed-off-by: Antonin Godard --- doc/nvim-tree-lua.txt | 11 +++ lua/nvim-tree/actions/moves/item.lua | 129 ++++++++++++++++++++++++--- lua/nvim-tree/api.lua | 2 + 3 files changed, 129 insertions(+), 13 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index c656b7c3751..7e50eb53d43 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -1887,6 +1887,11 @@ node.navigate.git.next_skip_gitignored() node.navigate.git.prev() *nvim-tree-api.node.navigate.git.prev()* Navigate to the previous item showing git status. + *nvim-tree-api.node.navigate.git.prev_recursive()* +node.navigate.git.prev_recursive() + Same as |node.navigate.git.prev()|, but navigates to next item showing git + status recursively. Needs `git.show_on_dirs` set to `true`. + *nvim-tree-api.node.navigate.git.prev_skip_gitignored()* node.navigate.git.prev_skip_gitignored() Same as |node.navigate.git.prev()|, but skips gitignored files. @@ -1905,6 +1910,12 @@ node.navigate.diagnostics.next_recursive() node.navigate.diagnostics.prev() Navigate to the next item showing diagnostic status. + *nvim-tree-api.node.navigate.diagnostics.prev_recursive()* +node.navigate.diagnostics.prev_recursive() + Same as |node.navigate.diagnostics.prev()|, but navigates to previous item + showing diagnostic status recursively.Needs `diagnostics.show_on_dirs` and + `diagnostics.show_on_open_dirs` set to `true`. + *nvim-tree-api.node.navigate.opened.next()* node.navigate.opened.next() Navigate to the next |bufloaded()| item. diff --git a/lua/nvim-tree/actions/moves/item.lua b/lua/nvim-tree/actions/moves/item.lua index 12a8eb3dba1..1528537e8f0 100644 --- a/lua/nvim-tree/actions/moves/item.lua +++ b/lua/nvim-tree/actions/moves/item.lua @@ -67,9 +67,18 @@ local function move(where, what, skip_gitignored) end end ----@param opts NavigationItemOpts +local function expand_node(node) + if not node.open then + -- Expand the node. + -- Should never collapse since we checked open. + lib.expand_or_collapse(node) + end +end + +--- Move to the next node recursively. +---@param what string type of status ---@param skip_gitignored boolean default false -local function move_next_recursive(opts, skip_gitignored) +local function move_next_recursive(what, skip_gitignored) -- If the current node: -- * is a directory -- * and has a git/diag status @@ -79,12 +88,12 @@ local function move_next_recursive(opts, skip_gitignored) if not node_init then return end - local valid = status_is_valid(node_init, opts.what, skip_gitignored) + local valid = status_is_valid(node_init, what, skip_gitignored) if node_init.nodes ~= nil and valid and not node_init.open then lib.expand_or_collapse(node_init) end - move(opts.where, opts.what, skip_gitignored) + move("next", what, skip_gitignored) local node_cur = lib.get_node_at_cursor() if not node_cur then @@ -100,13 +109,9 @@ local function move_next_recursive(opts, skip_gitignored) local i = 0 local is_dir = node_cur.nodes ~= nil while is_dir and i < MAX_DEPTH do - if not node_cur.open then - -- Expand the node. - -- Should never collapse since we checked open. - lib.expand_or_collapse(node_cur) - end + expand_node(node_cur) - move(opts.where, opts.what, skip_gitignored) + move("next", what, skip_gitignored) -- Save current node. node_cur = lib.get_node_at_cursor() @@ -121,6 +126,100 @@ local function move_next_recursive(opts, skip_gitignored) end end +-- Find the line number of a node. +-- Return -1 is node is nil or not found. +---@param node Node|nil +---@return integer +local function find_node_line(node) + if not node then + return -1 + end + + local first_node_line = core.get_nodes_starting_line() + local nodes_by_line = utils.get_nodes_by_line(core.get_explorer().nodes, first_node_line) + local iter_start, iter_end = first_node_line, #nodes_by_line + + for line = iter_start, iter_end, 1 do + if nodes_by_line[line] == node then + return line + end + end + + return -1 +end + +--- Move to the previous node recursively. +--- +--- move_prev_recursive: +--- +--- 1) Save current as node_init. +-- 2) Call a non-recursive prev. +--- 3) If current node is node_init's parent, call move_prev_recursive. +--- 4) Else: +--- 4.1) If current node is nil, is node_init (we didn't move), or is a file, return. +--- 4.2) The current file is a directory, expand it. +--- 4.3) Find node_init in current window, and move to it (if not found, return). +--- If node_init is the root node (name = ".."), directly move to position 1. +--- 4.4) Call a non-recursive prev. +--- 4.5) Save the current node and start back from 4.1. +--- +---@param what string type of status +---@param skip_gitignored boolean default false +local function move_prev_recursive(what, skip_gitignored) + local node_init, node_cur + + -- 1) + node_init = lib.get_node_at_cursor() + if node_init == nil then + return + end + + -- 2) + move("prev", what, skip_gitignored) + + node_cur = lib.get_node_at_cursor() + if node_cur == node_init.parent then + -- 3) + move_prev_recursive(what, skip_gitignored) + else + -- i is used to limit iterations. + local i = 0 + while i < MAX_DEPTH do + -- 4.1) + if + node_cur == nil + or node_cur == node_init -- we didn't move + or not node_cur.nodes -- node is a file + then + return + end + + -- 4.2) + local node_dir = node_cur + expand_node(node_dir) + + -- 4.3) + if node_init.name == ".." then -- root node + view.set_cursor { 1, 0 } -- move to root node (position 1) + else + local node_init_line = find_node_line(node_init) + if node_init_line < 0 then + return + end + view.set_cursor { node_init_line, 0 } + end + + -- 4.4) + move("prev", what, skip_gitignored) + + -- 4.5) + node_cur = lib.get_node_at_cursor() + + i = i + 1 + end + end +end + ---@class NavigationItemOpts ---@field where string ---@field what string @@ -132,8 +231,8 @@ function M.fn(opts) local recurse = false local skip_gitignored = false - -- recurse only available for "next" git and diag moves. - if opts.where == "next" and (opts.what == "git" or opts.what == "diag") and opts.recurse ~= nil then + -- recurse only valid for git and diag moves. + if (opts.what == "git" or opts.what == "diag") and opts.recurse ~= nil then recurse = opts.recurse end @@ -146,7 +245,11 @@ function M.fn(opts) return end - move_next_recursive(opts, skip_gitignored) + if opts.where == "next" then + move_next_recursive(opts.what, skip_gitignored) + elseif opts.where == "prev" then + move_prev_recursive(opts.what, skip_gitignored) + end end end diff --git a/lua/nvim-tree/api.lua b/lua/nvim-tree/api.lua index c7be8cee93d..3c85071e899 100644 --- a/lua/nvim-tree/api.lua +++ b/lua/nvim-tree/api.lua @@ -213,9 +213,11 @@ Api.node.navigate.git.next_skip_gitignored = wrap_node(actions.moves.item.fn { w 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" }) From cc6def0a878ec58a730100a7df4947e8a00395a5 Mon Sep 17 00:00:00 2001 From: Antonin Godard Date: Sun, 3 Dec 2023 12:01:54 -0800 Subject: [PATCH 4/7] fix(#1389): next recursive: take root node into account The root node cannot have a status. Previously if moving from the root node, status_is_valid was trying to fetch the status from it and errored. Signed-off-by: Antonin Godard --- lua/nvim-tree/actions/moves/item.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lua/nvim-tree/actions/moves/item.lua b/lua/nvim-tree/actions/moves/item.lua index 1528537e8f0..8ba002bfbed 100644 --- a/lua/nvim-tree/actions/moves/item.lua +++ b/lua/nvim-tree/actions/moves/item.lua @@ -81,6 +81,7 @@ end local function move_next_recursive(what, skip_gitignored) -- If the current node: -- * is a directory + -- * and is not the root node -- * and has a git/diag status -- * and is not opened -- expand it. @@ -88,7 +89,10 @@ local function move_next_recursive(what, skip_gitignored) if not node_init then return end - local valid = status_is_valid(node_init, what, skip_gitignored) + local valid = false + if node_init.name ~= ".." then -- root node cannot have a status + valid = status_is_valid(node_init, what, skip_gitignored) + end if node_init.nodes ~= nil and valid and not node_init.open then lib.expand_or_collapse(node_init) end From ed2b2d543364f5637da56f8efd233391700977b3 Mon Sep 17 00:00:00 2001 From: Antonin Godard Date: Sat, 6 Jan 2024 09:32:35 -0800 Subject: [PATCH 5/7] fix(#1389): doc: remove show_on_open_dirs limitation Signed-off-by: Antonin Godard --- doc/nvim-tree-lua.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 7e50eb53d43..c075724c9e4 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -1904,7 +1904,7 @@ node.navigate.diagnostics.next() node.navigate.diagnostics.next_recursive() Same as |node.navigate.diagnostics.next()|, but navigates to next item showing diagnostic status recursively. Needs `diagnostics.show_on_dirs` - and `diagnostics.show_on_open_dirs` set to `true`. + set to `true`. *nvim-tree-api.node.navigate.diagnostics.prev()* node.navigate.diagnostics.prev() @@ -1913,8 +1913,8 @@ node.navigate.diagnostics.prev() *nvim-tree-api.node.navigate.diagnostics.prev_recursive()* node.navigate.diagnostics.prev_recursive() Same as |node.navigate.diagnostics.prev()|, but navigates to previous item - showing diagnostic status recursively.Needs `diagnostics.show_on_dirs` and - `diagnostics.show_on_open_dirs` set to `true`. + showing diagnostic status recursively. Needs `diagnostics.show_on_dirs` set + to `true`. *nvim-tree-api.node.navigate.opened.next()* node.navigate.opened.next() From e54aa1846b4ffa7c3d8bb89673b341372fb1438c Mon Sep 17 00:00:00 2001 From: Antonin Godard Date: Sat, 6 Jan 2024 09:33:10 -0800 Subject: [PATCH 6/7] feat(#1389): move find_node_line to utils Signed-off-by: Antonin Godard --- lua/nvim-tree/actions/moves/item.lua | 24 +----------------------- lua/nvim-tree/utils.lua | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lua/nvim-tree/actions/moves/item.lua b/lua/nvim-tree/actions/moves/item.lua index 8ba002bfbed..3803a06fe44 100644 --- a/lua/nvim-tree/actions/moves/item.lua +++ b/lua/nvim-tree/actions/moves/item.lua @@ -130,28 +130,6 @@ local function move_next_recursive(what, skip_gitignored) end end --- Find the line number of a node. --- Return -1 is node is nil or not found. ----@param node Node|nil ----@return integer -local function find_node_line(node) - if not node then - return -1 - end - - local first_node_line = core.get_nodes_starting_line() - local nodes_by_line = utils.get_nodes_by_line(core.get_explorer().nodes, first_node_line) - local iter_start, iter_end = first_node_line, #nodes_by_line - - for line = iter_start, iter_end, 1 do - if nodes_by_line[line] == node then - return line - end - end - - return -1 -end - --- Move to the previous node recursively. --- --- move_prev_recursive: @@ -206,7 +184,7 @@ local function move_prev_recursive(what, skip_gitignored) if node_init.name == ".." then -- root node view.set_cursor { 1, 0 } -- move to root node (position 1) else - local node_init_line = find_node_line(node_init) + local node_init_line = utils.find_node_line(node_init) if node_init_line < 0 then return end diff --git a/lua/nvim-tree/utils.lua b/lua/nvim-tree/utils.lua index fe1b2481170..6e20bdfa98b 100644 --- a/lua/nvim-tree/utils.lua +++ b/lua/nvim-tree/utils.lua @@ -116,6 +116,28 @@ function M.find_node(nodes, fn) return node, i end +-- Find the line number of a node. +-- Return -1 is node is nil or not found. +---@param node Node|nil +---@return integer +function M.find_node_line(node) + if not node then + return -1 + end + + local first_node_line = require("nvim-tree.core").get_nodes_starting_line() + local nodes_by_line = M.get_nodes_by_line(require("nvim-tree.core").get_explorer().nodes, first_node_line) + local iter_start, iter_end = first_node_line, #nodes_by_line + + for line = iter_start, iter_end, 1 do + if nodes_by_line[line] == node then + return line + end + end + + return -1 +end + -- get the node in the tree state depending on the absolute path of the node -- (grouped or hidden too) ---@param path string From 2d1dd9379b24ddf62da36445629060a081de7f00 Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Sun, 7 Jan 2024 09:03:18 +1100 Subject: [PATCH 7/7] feat(#1389): doc: note recursive moves are to files only, tidy --- doc/nvim-tree-lua.txt | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index c075724c9e4..baec6ca8a26 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -1875,10 +1875,11 @@ node.open.preview_no_picker() *nvim-tree-api.node.open.preview_no_picker()* node.navigate.git.next() *nvim-tree-api.node.navigate.git.next()* Navigate to the next item showing git status. - *nvim-tree-api.node.navigate.git.next_recursive()* + *nvim-tree-api.node.navigate.git.next_recursive()* node.navigate.git.next_recursive() - Same as |node.navigate.git.next()|, but navigates to next item showing git - status recursively. Needs `git.show_on_dirs` set to `true`. + Alternative to |nvim-tree-api.node.navigate.git.next()| that navigates to + the next file showing git status, recursively. + Needs |nvim-tree.git.show_on_dirs| set. *nvim-tree-api.node.navigate.git.next_skip_gitignored()* node.navigate.git.next_skip_gitignored() @@ -1889,8 +1890,9 @@ node.navigate.git.prev() *nvim-tree-api.node.navigate.git.prev()* *nvim-tree-api.node.navigate.git.prev_recursive()* node.navigate.git.prev_recursive() - Same as |node.navigate.git.prev()|, but navigates to next item showing git - status recursively. Needs `git.show_on_dirs` set to `true`. + Alternative to |nvim-tree-api.node.navigate.git.prev()| that navigates to + the previous file showing git status, recursively. + Needs |nvim-tree.git.show_on_dirs| set. *nvim-tree-api.node.navigate.git.prev_skip_gitignored()* node.navigate.git.prev_skip_gitignored() @@ -1900,21 +1902,21 @@ node.navigate.git.prev_skip_gitignored() node.navigate.diagnostics.next() Navigate to the next item showing diagnostic status. - *nvim-tree-api.node.navigate.diagnostics.next_recursive()* + *nvim-tree-api.node.navigate.diagnostics.next_recursive()* node.navigate.diagnostics.next_recursive() - Same as |node.navigate.diagnostics.next()|, but navigates to next item - showing diagnostic status recursively. Needs `diagnostics.show_on_dirs` - set to `true`. + Alternative to |nvim-tree-api.node.navigate.diagnostics.next()| that + navigates to the next file showing diagnostic status, recursively. + Needs |nvim-tree.diagnostics.show_on_dirs| set. *nvim-tree-api.node.navigate.diagnostics.prev()* node.navigate.diagnostics.prev() Navigate to the next item showing diagnostic status. - *nvim-tree-api.node.navigate.diagnostics.prev_recursive()* + *nvim-tree-api.node.navigate.diagnostics.prev_recursive()* node.navigate.diagnostics.prev_recursive() - Same as |node.navigate.diagnostics.prev()|, but navigates to previous item - showing diagnostic status recursively. Needs `diagnostics.show_on_dirs` set - to `true`. + Alternative to |nvim-tree-api.node.navigate.diagnostics.prev()| that + navigates to the previous file showing diagnostic status, recursively. + Needs |nvim-tree.diagnostics.show_on_dirs| set. *nvim-tree-api.node.navigate.opened.next()* node.navigate.opened.next()