Skip to content

Commit 4c74126

Browse files
committed
WIP, about to add a BaseSource
1 parent b2302a3 commit 4c74126

File tree

6 files changed

+251
-32
lines changed

6 files changed

+251
-32
lines changed

lua/neo-tree.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ local define_events = function()
6464
events.define_autocmd_event(events.VIM_BUFFER_ENTER, { "BufEnter", "BufWinEnter" }, 0)
6565
events.define_autocmd_event(events.VIM_WIN_ENTER, { "WinEnter" }, 0)
6666
events.define_autocmd_event(events.VIM_DIR_CHANGED, { "DirChanged" }, 200)
67+
events.define_autocmd_event(events.VIM_TAB_CLOSED, { "TabClosed" })
6768
events_setup = true
6869
end
6970

lua/neo-tree/events/init.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ local M = {
1919
VIM_BUFFER_ENTER = "vim_buffer_enter",
2020
VIM_DIAGNOSTIC_CHANGED = "vim_diagnostic_changed",
2121
VIM_DIR_CHANGED = "vim_dir_changed",
22+
VIM_TAB_CLOSED = "vim_tab_closed",
2223
VIM_WIN_ENTER = "vim_win_enter",
2324
}
2425

2526
M.define_autocmd_event = function(event_name, autocmds, debounce_frequency, seed_fn)
2627
local opts = {
2728
setup = function()
28-
local tpl = ":lua require('neo-tree.events').fire_event('%s')"
29+
local tpl = ":lua require('neo-tree.events').fire_event('%s', '<afile>')"
2930
local callback = string.format(tpl, event_name)
3031
local cmds = {
3132
"augroup NeoTreeEvent_" .. event_name,
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
--This file should have all functions that are in the public api and either set
2+
--or read the state of this source.
3+
4+
local vim = vim
5+
local utils = require("neo-tree.utils")
6+
local fs_scan = require("neo-tree.sources.filesystem.lib.fs_scan")
7+
local renderer = require("neo-tree.ui.renderer")
8+
local events = require("neo-tree.events")
9+
local log = require("neo-tree.log")
10+
11+
local BaseSource = {}
12+
function BaseSource:new()
13+
local props = {}
14+
setmetatable(props, self)
15+
self.__index = self
16+
return props
17+
end
18+
19+
local default_config = nil
20+
local state_by_tab = {}
21+
22+
local get_state = function(tabnr)
23+
tabnr = tabnr or vim.api.nvim_get_current_tabpage()
24+
local state = state_by_tab[tabnr]
25+
if not state then
26+
state = utils.table_copy(default_config)
27+
state.tabnr = tabnr
28+
state_by_tab[tabnr] = state
29+
end
30+
return state
31+
end
32+
33+
local get_path_to_reveal = function()
34+
if vim.bo.filetype == "neo-tree" then
35+
return nil
36+
end
37+
local path = vim.fn.expand("%:p")
38+
if not path or path == "" or path:match("term://") then
39+
return nil
40+
end
41+
return path
42+
end
43+
44+
BaseSource.subscribe = function(event)
45+
local state = get_state()
46+
if not state.subscriptions then
47+
state.subscriptions = {}
48+
end
49+
state.subscriptions[event] = true
50+
events.subscribe(event)
51+
end
52+
53+
BaseSource.unsubscribe = function(event, state)
54+
state = state or get_state()
55+
if state.subscriptions then
56+
state.subscriptions[event] = false
57+
end
58+
events.unsubscribe(event)
59+
end
60+
61+
BaseSource.close = function()
62+
local state = get_state()
63+
return renderer.close(state)
64+
end
65+
66+
---Redraws the tree with updated diagnostics without scanning the filesystem again.
67+
BaseSource.diagnostics_changed = function(args)
68+
local state = get_state()
69+
args = args or {}
70+
state.diagnostics_lookup = args.diagnostics_lookup
71+
if renderer.window_exists(state) then
72+
state.tree:render()
73+
end
74+
end
75+
76+
---Called by autocmds when the cwd dir is changed. This will change the root.
77+
BaseSource.dir_changed = function()
78+
local state = get_state()
79+
local cwd = vim.fn.getcwd()
80+
if state.path and cwd == state.path then
81+
return
82+
end
83+
if state.path and renderer.window_exists(state) then
84+
BaseSource.navigate(cwd)
85+
end
86+
end
87+
88+
BaseSource.dispose = function(tabnr)
89+
local state = get_state(tabnr)
90+
fs_scan.stop_watchers(state)
91+
renderer.close(state)
92+
for event, subscribed in pairs(state.subscriptions) do
93+
if subscribed then
94+
unsubscribe(event, state)
95+
end
96+
end
97+
state_by_tab[state.tabnr] = nil
98+
end
99+
100+
BaseSource.float = function()
101+
local state = get_state()
102+
state.force_float = true
103+
local path_to_reveal = get_path_to_reveal()
104+
BaseSource.navigate(state.path, path_to_reveal)
105+
end
106+
107+
---Focus the window, opening it if it is not already open.
108+
---@param path_to_reveal string Node to focus after the items are loaded.
109+
---@param callback function Callback to call after the items are loaded.
110+
BaseSource.focus = function(path_to_reveal, callback)
111+
local state = get_state()
112+
if path_to_reveal then
113+
BaseSource.navigate(state.path, path_to_reveal, callback)
114+
else
115+
if renderer.window_exists(state) then
116+
vim.api.nvim_set_current_win(state.winid)
117+
else
118+
BaseSource.navigate(state.path, nil, callback)
119+
end
120+
end
121+
end
122+
123+
---Navigate to the given path.
124+
---@param path string Path to navigate to. If empty, will navigate to the cwd.
125+
---@param path_to_reveal string Node to focus after the items are loaded.
126+
---@param callback function Callback to call after the items are loaded.
127+
BaseSource.navigate = function(path, path_to_reveal, callback)
128+
local state = get_state()
129+
log.error(state.name .. ".navigate() must be overwritten!")
130+
end
131+
132+
BaseSource.reveal_current_file = function(toggle_if_open)
133+
local state = get_state()
134+
log.error(state.name .. ".reveal_current_file() must be overwritten!")
135+
end
136+
137+
---Redraws the tree without loading items again. Use this after
138+
-- making changes to the nodes that would affect how their components are
139+
-- rendered.
140+
BaseSource.redraw = function()
141+
local state = get_state()
142+
if renderer.window_exists(state) then
143+
state.tree:render()
144+
end
145+
end
146+
147+
---Refreshes the tree by loading the items again.
148+
BaseSource.refresh = function(callback)
149+
local state = get_state()
150+
if state.path and renderer.window_exists(state) then
151+
if type(callback) ~= "function" then
152+
callback = nil
153+
end
154+
BaseSource.navigate(state.path, nil, callback)
155+
end
156+
end
157+
158+
---Configures the plugin, should be called before the plugin is used.
159+
---@param config table Configuration table containing any keys that the user
160+
--wants to change from the defaults. May be empty to accept default values.
161+
BaseSource.setup = function(config, global_config)
162+
default_config = config
163+
log.error(state.name .. ".setup() must be overwritten!")
164+
end
165+
166+
---Opens the tree and displays the current path or cwd.
167+
---@param callback function Callback to call after the items are loaded.
168+
BaseSource.show = function(callback)
169+
local state = get_state()
170+
BaseSource.navigate(state.path, nil, callback)
171+
end
172+
173+
return BaseSource

lua/neo-tree/sources/filesystem/init.lua

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ local M = {}
1313
local default_config = nil
1414
local state_by_tab = {}
1515

16-
local get_state = function()
17-
local tabnr = vim.api.nvim_get_current_tabpage()
16+
local get_state = function(tabnr)
17+
tabnr = tabnr or vim.api.nvim_get_current_tabpage()
1818
local state = state_by_tab[tabnr]
1919
if not state then
2020
state = utils.table_copy(default_config)
@@ -48,6 +48,23 @@ local get_path_to_reveal = function()
4848
return path
4949
end
5050

51+
local subscribe = function(event)
52+
local state = get_state()
53+
if not state.subscriptions then
54+
state.subscriptions = {}
55+
end
56+
state.subscriptions[event] = true
57+
events.subscribe(event)
58+
end
59+
60+
local unsubscribe = function(event, state)
61+
state = state or get_state()
62+
if state.subscriptions then
63+
state.subscriptions[event] = false
64+
end
65+
events.unsubscribe(event)
66+
end
67+
5168
M.close = function()
5269
local state = get_state()
5370
return renderer.close(state)
@@ -75,6 +92,18 @@ M.dir_changed = function()
7592
end
7693
end
7794

95+
M.dispose = function(tabnr)
96+
local state = get_state(tabnr)
97+
fs_scan.stop_watchers(state)
98+
renderer.close(state)
99+
for event, subscribed in pairs(state.subscriptions) do
100+
if subscribed then
101+
unsubscribe(event, state)
102+
end
103+
end
104+
state_by_tab[state.tabnr] = nil
105+
end
106+
78107
M.float = function()
79108
local state = get_state()
80109
state.force_float = true
@@ -280,13 +309,13 @@ M.setup = function(config, global_config)
280309

281310
--Configure events for before_render
282311
local before_render_id = config.name .. ".before_render"
283-
events.unsubscribe({
312+
unsubscribe({
284313
event = events.BEFORE_RENDER,
285314
id = before_render_id,
286315
})
287316
if config.before_render then
288317
--convert to new event system
289-
events.subscribe({
318+
subscribe({
290319
event = events.BEFORE_RENDER,
291320
handler = function(state)
292321
local this_state = get_state()
@@ -297,7 +326,7 @@ M.setup = function(config, global_config)
297326
id = before_render_id,
298327
})
299328
elseif global_config.enable_git_status then
300-
events.subscribe({
329+
subscribe({
301330
event = events.BEFORE_RENDER,
302331
handler = function(state)
303332
local this_state = get_state()
@@ -321,37 +350,37 @@ M.setup = function(config, global_config)
321350
id = "filesystem." .. events.FS_EVENT,
322351
}
323352
if config.use_libuv_file_watcher then
324-
events.unsubscribe(buf_watcher)
325-
events.subscribe(fs_watcher)
353+
unsubscribe(buf_watcher)
354+
subscribe(fs_watcher)
326355
else
327-
events.unsubscribe(fs_watcher)
356+
unsubscribe(fs_watcher)
328357
require("neo-tree.sources.filesystem.lib.fs_watch").unwatch_all()
329-
events.subscribe(buf_watcher)
358+
subscribe(buf_watcher)
330359
end
331360

332361
--Configure event handlers for cwd changes
333362
if default_config.bind_to_cwd then
334-
events.subscribe({
363+
subscribe({
335364
event = events.VIM_DIR_CHANGED,
336365
handler = M.dir_changed,
337366
id = "filesystem." .. events.VIM_DIR_CHANGED,
338367
})
339368
else
340-
events.unsubscribe({
369+
unsubscribe({
341370
event = events.VIM_DIR_CHANGED,
342371
id = "filesystem." .. events.VIM_DIR_CHANGED,
343372
})
344373
end
345374

346375
--Configure event handlers for lsp diagnostic updates
347376
if global_config.enable_diagnostics then
348-
events.subscribe({
377+
subscribe({
349378
event = events.VIM_DIAGNOSTIC_CHANGED,
350379
handler = M.diagnostics_changed,
351380
id = "filesystem." .. events.VIM_DIAGNOSTIC_CHANGED,
352381
})
353382
else
354-
events.unsubscribe({
383+
unsubscribe({
355384
event = events.VIM_DIAGNOSTIC_CHANGED,
356385
id = "filesystem." .. events.VIM_DIAGNOSTIC_CHANGED,
357386
})

lua/neo-tree/sources/filesystem/lib/fs_scan.lua

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,8 @@ local function do_scan(context, path_to_scan)
6666
end
6767

6868
M.get_items_async = function(state, parent_id, path_to_reveal, callback)
69-
if state.use_libuv_file_watcher and state.tree then
70-
-- unwatch any folders that were previously being watched
71-
local loaded_folders = renderer.select_nodes(state.tree, function(node)
72-
return node.type == "directory" and node.loaded
73-
end)
74-
for _, folder in ipairs(loaded_folders) do
75-
fs_watch.unwatch_folder(folder.link_to or folder:get_id())
76-
end
69+
if not parent_id then
70+
M.stop_watchers(state)
7771
end
7872
local context = file_items.create_context(state)
7973

@@ -149,4 +143,17 @@ M.get_items_async = function(state, parent_id, path_to_reveal, callback)
149143
end
150144
end
151145

146+
M.stop_watchers = function(state)
147+
if state.use_libuv_file_watcher and state.tree then
148+
-- We are loaded a new root or refreshing, unwatch any folders that were
149+
-- previously being watched.
150+
local loaded_folders = renderer.select_nodes(state.tree, function(node)
151+
return node.type == "directory" and node.loaded
152+
end)
153+
for _, folder in ipairs(loaded_folders) do
154+
fs_watch.unwatch_folder(folder.link_to or folder:get_id())
155+
end
156+
end
157+
end
158+
152159
return M

0 commit comments

Comments
 (0)