Skip to content

Commit 6f24b60

Browse files
committed
feat(marks): add navigation next and previous
1 parent 078a9e5 commit 6f24b60

File tree

5 files changed

+122
-17
lines changed

5 files changed

+122
-17
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/node/open-file.lua

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -220,17 +220,6 @@ local function open_in_new_window(filename, mode, win_ids)
220220
lib.set_target_win()
221221
end
222222

223-
local function is_already_open(filename, win_ids)
224-
for _, id in ipairs(win_ids) do
225-
if filename == api.nvim_buf_get_name(api.nvim_win_get_buf(id)) then
226-
api.nvim_set_current_win(id)
227-
return true
228-
end
229-
end
230-
231-
return false
232-
end
233-
234223
local function is_already_loaded(filename)
235224
for _, buf_id in ipairs(api.nvim_list_bufs()) do
236225
if api.nvim_buf_is_loaded(buf_id) and filename == api.nvim_buf_get_name(buf_id) then
@@ -258,7 +247,7 @@ function M.fn(mode, filename)
258247
local win_ids = api.nvim_tabpage_list_wins(tabpage)
259248
local buf_loaded = is_already_loaded(filename)
260249

261-
local found = is_already_open(filename, win_ids)
250+
local found = utils.is_in_displayed_buffer(filename)
262251
if found and mode == "preview" then
263252
return
264253
end

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

Lines changed: 5 additions & 4 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
@@ -51,13 +51,14 @@ function M.draw()
5151
M.clear()
5252

5353
local buf = view.get_bufnr()
54+
local add = core.get_nodes_starting_line() - 1
5455
Iterator.builder(core.get_explorer().nodes)
5556
:recursor(function(node)
5657
return node.open and node.nodes
5758
end)
5859
:applier(function(node, idx)
5960
if M.get_mark(node) then
60-
vim.fn.sign_place(0, GROUP, SIGN_NAME, buf, { lnum = idx + 1, priority = 3 })
61+
vim.fn.sign_place(0, GROUP, SIGN_NAME, buf, { lnum = idx + add, priority = 3 })
6162
end
6263
end)
6364
:iterate()

lua/nvim-tree/marks/navigation.lua

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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_nearest(node, where)
9+
local first, prev, next, last = nil, nil, nil, nil
10+
local found = false
11+
12+
Iterator.builder(core.get_explorer().nodes)
13+
:recursor(function(n)
14+
return n.open and n.nodes
15+
end)
16+
:applier(function(n)
17+
if n.absolute_path == node.absolute_path then
18+
found = true
19+
return
20+
end
21+
22+
if not Marks.get_mark(n) then
23+
return
24+
end
25+
26+
last = n
27+
first = first or n
28+
29+
if found and not next then
30+
next = n
31+
end
32+
33+
if not found then
34+
prev = n
35+
end
36+
end)
37+
:iterate()
38+
39+
if not found then
40+
return
41+
end
42+
43+
if where == "next" then
44+
return next or first
45+
else
46+
return prev or last
47+
end
48+
end
49+
50+
local function get(where, node)
51+
if node then
52+
return get_nearest(node, where)
53+
end
54+
end
55+
56+
local function open_or_focus(node)
57+
if node and not node.nodes and not utils.is_in_displayed_buffer(node.absolute_path) then
58+
open_file.fn("edit", node.absolute_path)
59+
elseif node then
60+
utils.focus_file(node.absolute_path)
61+
end
62+
end
63+
64+
local function navigate_to(where)
65+
return function()
66+
local node = lib.get_node_at_cursor()
67+
local next = get(where, node)
68+
open_or_focus(next)
69+
end
70+
end
71+
72+
local M = {}
73+
74+
M.next = navigate_to "next"
75+
M.prev = navigate_to "prev"
76+
77+
function M.select()
78+
local list = vim.tbl_map(function(n)
79+
return n.absolute_path
80+
end, Marks.get_marks())
81+
82+
vim.ui.select(list, {
83+
prompt = "Select a file to open or a folder to focus",
84+
}, function(choice)
85+
if not choice or choice == "" then
86+
return
87+
end
88+
local node = Marks.get_mark { absolute_path = choice }
89+
open_or_focus(node)
90+
end)
91+
end
92+
93+
return M

lua/nvim-tree/utils.lua

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,4 +335,14 @@ function M.focus_file(path)
335335
require("nvim-tree.view").set_cursor { i + 1, 1 }
336336
end
337337

338+
function M.is_in_displayed_buffer(path)
339+
for _, w in pairs(vim.api.nvim_tabpage_list_wins(0)) do
340+
local b = vim.api.nvim_win_get_buf(w)
341+
if vim.api.nvim_buf_get_name(b) == path then
342+
return true
343+
end
344+
end
345+
return false
346+
end
347+
338348
return M

0 commit comments

Comments
 (0)