Skip to content

Commit 3efc241

Browse files
committed
feat(marks): add navigation next and previous
1 parent df92f15 commit 3efc241

File tree

5 files changed

+136
-12
lines changed

5 files changed

+136
-12
lines changed

doc/nvim-tree-lua.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,18 @@ You can toggle marks on files/folders with
12621262
default.
12631263

12641264
To get the list of marked paths, you can call
1265-
`require("nvim-tree.marks").get_marks()`. This will return `{string}`.
1265+
`require("nvim-tree.marks").get_marks()`. This will return `{node}`.
1266+
1267+
*nvim-tree.bookmarks.navigation*
1268+
1269+
Navigation for marks is not bound by default in nvim-tree because we don't
1270+
want to focus the tree view each time we wish to switch to another mark.
1271+
1272+
This requires binding bookmark navigation yourself.
1273+
1274+
-- in your lua configuration
1275+
vim.keymap.set("n", "<leader>mn", require("nvim-tree.marks.navigation").next)
1276+
vim.keymap.set("n", "<leader>mp", require("nvim-tree.marks.navigation").prev)
1277+
vim.keymap.set("n", "<leader>ms", require("nvim-tree.marks.navigation").select)
12661278

12671279
vim:tw=78:ts=4:sw=4:et:ft=help:norl:

lua/nvim-tree/actions/fs/create-file.lua

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,6 @@ local core = require "nvim-tree.core"
88

99
local M = {}
1010

11-
local function focus_file(file)
12-
local _, i = utils.find_node(core.get_explorer().nodes, function(node)
13-
return node.absolute_path == file
14-
end)
15-
require("nvim-tree.view").set_cursor { i + 1, 1 }
16-
end
17-
1811
local function create_file(file)
1912
if utils.file_exists(file) then
2013
print(file .. " already exists. Overwrite? y/n")
@@ -112,7 +105,7 @@ function M.fn(node)
112105
end
113106
-- INFO: defer needed when reload is automatic (watchers)
114107
vim.defer_fn(function()
115-
focus_file(new_file_path)
108+
utils.focus_file(new_file_path)
116109
end, 150)
117110
end)
118111
end

lua/nvim-tree/marks.lua renamed to lua/nvim-tree/marks/init.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ local NvimTreeMarks = {}
77
local M = {}
88

99
local function add_mark(node)
10-
NvimTreeMarks[node.absolute_path] = true
10+
NvimTreeMarks[node.absolute_path] = node
1111
M.draw()
1212
end
1313

@@ -30,8 +30,8 @@ end
3030

3131
function M.get_marks()
3232
local list = {}
33-
for k in pairs(NvimTreeMarks) do
34-
table.insert(list, k)
33+
for _, n in pairs(NvimTreeMarks) do
34+
table.insert(list, n)
3535
end
3636
return list
3737
end

lua/nvim-tree/marks/navigation.lua

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
local Iterator = require "nvim-tree.iterators.node-iterator"
2+
local core = require "nvim-tree.core"
3+
local Marks = require "nvim-tree.marks"
4+
local open_file = require "nvim-tree.actions.node.open-file"
5+
local utils = require "nvim-tree.utils"
6+
local lib = require "nvim-tree.lib"
7+
8+
local function get_prev_or_next_mark(node, idx_iter)
9+
local found_idx = -1
10+
local marks = Marks.get_marks()
11+
12+
for i, n in ipairs(marks) do
13+
if n.absolute_path == node.absolute_path then
14+
found_idx = i + idx_iter
15+
break
16+
end
17+
end
18+
19+
if found_idx == -1 then
20+
return
21+
end
22+
23+
if found_idx > #marks then
24+
found_idx = 1
25+
elseif found_idx == 0 then
26+
found_idx = #marks
27+
end
28+
29+
return marks[found_idx]
30+
end
31+
32+
local function get_nearest(node, where)
33+
local prev = nil
34+
local found = false
35+
36+
local next = Iterator.builder(core.get_explorer().nodes)
37+
:matcher(function()
38+
return found == true
39+
end)
40+
:recursor(function(n)
41+
return n.open and n.nodes
42+
end)
43+
:applier(function(n)
44+
if Marks.get_mark(n) then
45+
prev = n
46+
end
47+
if n.absolute_path == node.absolute_path then
48+
found = true
49+
end
50+
end)
51+
:iterate()
52+
53+
if found then
54+
if where == "next" then
55+
return next
56+
else
57+
return prev
58+
end
59+
end
60+
end
61+
62+
local function get(where, node)
63+
if not node then
64+
return Marks.get_marks()[1]
65+
end
66+
67+
local is_next = where == "next"
68+
if Marks.get_mark(node) then
69+
return get_prev_or_next_mark(node, is_next and 1 or -1)
70+
else
71+
return get_nearest(node, where)
72+
end
73+
end
74+
75+
local function open_or_focus(node)
76+
if node and not node.nodes then
77+
open_file.fn("edit", node.absolute_path)
78+
elseif next then
79+
utils.focus_file(node.absolute_path)
80+
end
81+
end
82+
83+
local function navigate_to(where)
84+
return function()
85+
local node = lib.get_node_at_cursor()
86+
local next = get(where, node)
87+
open_or_focus(next)
88+
end
89+
end
90+
91+
local M = {}
92+
93+
M.next = navigate_to "next"
94+
M.prev = navigate_to "prev"
95+
96+
function M.select()
97+
local list = vim.tbl_map(function(n)
98+
return n.absolute_path
99+
end, Marks.get_marks())
100+
101+
vim.ui.select(list, {
102+
prompt = "Select a file to open or a folder to focus",
103+
}, function(choice)
104+
if not choice or choice == "" then
105+
return
106+
end
107+
local node = Marks.get_mark { absolute_path = choice }
108+
open_or_focus(node)
109+
end)
110+
end
111+
112+
return M

lua/nvim-tree/utils.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,13 @@ function M.rename_loaded_buffers(old_path, new_path)
207207
end
208208
end
209209

210+
function M.focus_file(path)
211+
local _, i = M.find_node(require("nvim-tree.core").get_explorer().nodes, function(node)
212+
return node.absolute_path == path
213+
end)
214+
require("nvim-tree.view").set_cursor { i + 1, 1 }
215+
end
216+
210217
--- @param path string path to file or directory
211218
--- @return boolean
212219
function M.file_exists(path)

0 commit comments

Comments
 (0)