-
-
Notifications
You must be signed in to change notification settings - Fork 618
/
Copy pathlib.lua
218 lines (186 loc) · 5.45 KB
/
lib.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
local renderer = require "nvim-tree.renderer"
local view = require "nvim-tree.view"
local core = require "nvim-tree.core"
local utils = require "nvim-tree.utils"
local events = require "nvim-tree.events"
---@class LibOpenOpts
---@field path string|nil path
---@field current_window boolean|nil default false
---@field winid number|nil
local M = {
target_winid = nil,
}
---@return Node|nil
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 = vim.api.nvim_win_get_cursor(view.get_winnr())
local line = cursor[1]
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
---Create a sanitized partial copy of a node, populating children recursively.
---@param node Node|nil
---@return Node|nil cloned node
local function clone_node(node)
if not node then
node = core.get_explorer()
if not node then
return nil
end
end
local n = {
absolute_path = node.absolute_path,
executable = node.executable,
extension = node.extension,
git_status = node.git_status,
has_children = node.has_children,
hidden = node.hidden,
link_to = node.link_to,
name = node.name,
open = node.open,
type = node.type,
}
if type(node.nodes) == "table" then
n.nodes = {}
for _, child in ipairs(node.nodes) do
table.insert(n.nodes, clone_node(child))
end
end
return n
end
---Api.tree.get_nodes
---@return Node[]|nil
function M.get_nodes()
return clone_node(core.get_explorer())
end
-- If node is grouped, return the last node in the group. Otherwise, return the given node.
---@param node Node
---@return Node
function M.get_last_group_node(node)
while node and node.group_next do
node = node.group_next
end
---@diagnostic disable-next-line: return-type-mismatch -- it can't be nil
return node
end
---@param node Node
---@return Node[]
function M.get_all_nodes_in_group(node)
local next_node = utils.get_parent_of_group(node)
local nodes = {}
while next_node do
table.insert(nodes, next_node)
next_node = next_node.group_next
end
return nodes
end
---@param node Node
function M.expand_or_collapse(node)
if node.has_children then
node.has_children = false
end
if #node.nodes == 0 then
core.get_explorer():expand(node)
end
local open = not M.get_last_group_node(node).open
for _, n in ipairs(M.get_all_nodes_in_group(node)) do
n.open = open
end
renderer.draw()
end
function M.set_target_win()
local id = vim.api.nvim_get_current_win()
local tree_id = view.get_winnr()
if tree_id and id == tree_id then
M.target_winid = 0
return
end
M.target_winid = id
end
---@param cwd string
local function handle_buf_cwd(cwd)
if M.respect_buf_cwd and cwd ~= core.get_cwd() then
require("nvim-tree.actions.root.change-dir").fn(cwd)
end
end
local function open_view_and_draw()
local cwd = vim.fn.getcwd()
view.open()
handle_buf_cwd(cwd)
renderer.draw()
end
local function should_hijack_current_buf()
local bufnr = vim.api.nvim_get_current_buf()
local bufname = vim.api.nvim_buf_get_name(bufnr)
local bufmodified = vim.api.nvim_buf_get_option(bufnr, "modified")
local ft = vim.api.nvim_buf_get_option(bufnr, "ft")
local should_hijack_unnamed = M.hijack_unnamed_buffer_when_opening and bufname == "" and not bufmodified and ft == ""
local should_hijack_dir = bufname ~= "" and vim.fn.isdirectory(bufname) == 1 and M.hijack_directories.enable
return should_hijack_dir or should_hijack_unnamed
end
---@param prompt_input string
---@param prompt_select string
---@param items_short string[]
---@param items_long string[]
---@param kind string|nil
---@param callback fun(item_short: string)
function M.prompt(prompt_input, prompt_select, items_short, items_long, kind, callback)
local function format_item(short)
for i, s in ipairs(items_short) do
if short == s then
return items_long[i]
end
end
return ""
end
if M.select_prompts then
vim.ui.select(items_short, { prompt = prompt_select, kind = kind, format_item = format_item }, function(item_short)
callback(item_short)
end)
else
vim.ui.input({ prompt = prompt_input, default = items_short[1] or "" }, function(item_short)
if item_short then
callback(string.lower(item_short and item_short:sub(1, 1)) or nil)
end
end)
end
end
---Open the tree, initialising as needed. Maybe hijack the current buffer.
---@param opts LibOpenOpts|nil
function M.open(opts)
opts = opts or {}
M.set_target_win()
if not core.get_explorer() or opts.path then
core.init(opts.path or vim.loop.cwd())
end
if should_hijack_current_buf() then
view.close_this_tab_only()
view.open_in_win()
renderer.draw()
elseif opts.winid then
view.open_in_win { hijack_current_buf = false, resize = false, winid = opts.winid }
renderer.draw()
elseif opts.current_window then
view.open_in_win { hijack_current_buf = false, resize = false }
renderer.draw()
else
open_view_and_draw()
end
view.restore_tab_state()
events._dispatch_on_tree_open()
end
function M.setup(opts)
M.hijack_unnamed_buffer_when_opening = opts.hijack_unnamed_buffer_when_opening
M.hijack_directories = opts.hijack_directories
M.respect_buf_cwd = opts.respect_buf_cwd
M.select_prompts = opts.select_prompts
end
return M