-
Notifications
You must be signed in to change notification settings - Fork 251
/
Copy pathinit.lua
745 lines (672 loc) · 26.3 KB
/
init.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
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
local utils = require("neo-tree.utils")
local defaults = require("neo-tree.defaults")
local mapping_helper = require("neo-tree.setup.mapping-helper")
local events = require("neo-tree.events")
local log = require("neo-tree.log")
local file_nesting = require("neo-tree.sources.common.file-nesting")
local highlights = require("neo-tree.ui.highlights")
local manager = require("neo-tree.sources.manager")
local netrw = require("neo-tree.setup.netrw")
local hijack_cursor = require("neo-tree.sources.common.hijack_cursor")
local M = {}
local normalize_mappings = function(config)
if config == nil then
return false
end
local mappings = utils.get_value(config, "window.mappings", nil)
if mappings then
local fixed = mapping_helper.normalize_map(mappings)
config.window.mappings = fixed
return true
else
return false
end
end
local events_setup = false
local define_events = function()
if events_setup then
return
end
events.define_event(events.FS_EVENT, {
debounce_frequency = 100,
debounce_strategy = utils.debounce_strategy.CALL_LAST_ONLY,
})
local v = vim.version()
local diag_autocmd = "DiagnosticChanged"
if v.major < 1 and v.minor < 6 then
diag_autocmd = "User LspDiagnosticsChanged"
end
events.define_autocmd_event(events.VIM_DIAGNOSTIC_CHANGED, { diag_autocmd }, 500, function(args)
args.diagnostics_lookup = utils.get_diagnostic_counts()
return args
end)
local update_opened_buffers = function(args)
args.opened_buffers = utils.get_opened_buffers()
return args
end
events.define_autocmd_event(events.VIM_AFTER_SESSION_LOAD, { "SessionLoadPost" }, 200)
events.define_autocmd_event(events.VIM_BUFFER_ADDED, { "BufAdd" }, 200, update_opened_buffers)
events.define_autocmd_event(events.VIM_BUFFER_CHANGED, { "BufWritePost" }, 200)
events.define_autocmd_event(
events.VIM_BUFFER_DELETED,
{ "BufDelete" },
200,
update_opened_buffers
)
events.define_autocmd_event(events.VIM_BUFFER_ENTER, { "BufEnter", "BufWinEnter" }, 0)
events.define_autocmd_event(
events.VIM_BUFFER_MODIFIED_SET,
{ "BufModifiedSet" },
0,
update_opened_buffers
)
events.define_autocmd_event(events.VIM_COLORSCHEME, { "ColorScheme" }, 0)
events.define_autocmd_event(events.VIM_CURSOR_MOVED, { "CursorMoved" }, 100)
events.define_autocmd_event(events.VIM_DIR_CHANGED, { "DirChanged" }, 200, nil, true)
events.define_autocmd_event(events.VIM_INSERT_LEAVE, { "InsertLeave" }, 200)
events.define_autocmd_event(events.VIM_LEAVE, { "VimLeavePre" })
events.define_autocmd_event(events.VIM_RESIZED, { "VimResized" }, 100)
events.define_autocmd_event(events.VIM_TAB_CLOSED, { "TabClosed" })
events.define_autocmd_event(events.VIM_TERMINAL_ENTER, { "TermEnter" }, 0)
events.define_autocmd_event(events.VIM_TEXT_CHANGED_NORMAL, { "TextChanged" }, 200)
events.define_autocmd_event(events.VIM_WIN_CLOSED, { "WinClosed" })
events.define_autocmd_event(events.VIM_WIN_ENTER, { "WinEnter" }, 0, nil, true)
events.define_autocmd_event(events.GIT_EVENT, { "User FugitiveChanged" }, 100)
events.define_event(events.GIT_STATUS_CHANGED, { debounce_frequency = 0 })
events_setup = true
events.subscribe({
event = events.VIM_LEAVE,
handler = function()
events.clear_all_events()
end,
})
events.subscribe({
event = events.VIM_RESIZED,
handler = function()
require("neo-tree.ui.renderer").update_floating_window_layouts()
end,
})
end
local prior_window_options = {}
--- Store the current window options so we can restore them when we close the tree.
--- @param winid number | nil The window id to store the options for, defaults to current window
local store_local_window_settings = function(winid)
winid = winid or vim.api.nvim_get_current_win()
local neo_tree_settings_applied, _ =
pcall(vim.api.nvim_win_get_var, winid, "neo_tree_settings_applied")
if neo_tree_settings_applied then
-- don't store our own window settings
return
end
prior_window_options[tostring(winid)] = {
cursorline = vim.wo.cursorline,
cursorlineopt = vim.wo.cursorlineopt,
foldcolumn = vim.wo.foldcolumn,
wrap = vim.wo.wrap,
list = vim.wo.list,
spell = vim.wo.spell,
number = vim.wo.number,
relativenumber = vim.wo.relativenumber,
winhighlight = vim.wo.winhighlight,
}
end
--- Restore the window options for the current window
--- @param winid number | nil The window id to restore the options for, defaults to current window
local restore_local_window_settings = function(winid)
winid = winid or vim.api.nvim_get_current_win()
-- return local window settings to their prior values
local wo = prior_window_options[tostring(winid)]
if wo then
vim.wo.cursorline = wo.cursorline
vim.wo.cursorlineopt = wo.cursorlineopt
vim.wo.foldcolumn = wo.foldcolumn
vim.wo.wrap = wo.wrap
vim.wo.list = wo.list
vim.wo.spell = wo.spell
vim.wo.number = wo.number
vim.wo.relativenumber = wo.relativenumber
vim.wo.winhighlight = wo.winhighlight
log.debug("Window settings restored")
vim.api.nvim_win_set_var(0, "neo_tree_settings_applied", false)
else
log.debug("No window settings to restore")
end
end
local last_buffer_enter_filetype = nil
M.buffer_enter_event = function()
-- if it is a neo-tree window, just set local options
if vim.bo.filetype == "neo-tree" then
if last_buffer_enter_filetype == "neo-tree" then
-- we've switched to another neo-tree window
events.fire_event(events.NEO_TREE_BUFFER_LEAVE)
else
store_local_window_settings()
end
vim.cmd([[
setlocal cursorline
setlocal cursorlineopt=line
setlocal nowrap
setlocal nolist nospell nonumber norelativenumber
]])
local winhighlight =
"Normal:NeoTreeNormal,NormalNC:NeoTreeNormalNC,SignColumn:NeoTreeSignColumn,CursorLine:NeoTreeCursorLine,FloatBorder:NeoTreeFloatBorder,StatusLine:NeoTreeStatusLine,StatusLineNC:NeoTreeStatusLineNC,VertSplit:NeoTreeVertSplit,EndOfBuffer:NeoTreeEndOfBuffer"
if vim.version().minor >= 7 then
vim.cmd("setlocal winhighlight=" .. winhighlight .. ",WinSeparator:NeoTreeWinSeparator")
else
vim.cmd("setlocal winhighlight=" .. winhighlight)
end
events.fire_event(events.NEO_TREE_BUFFER_ENTER)
last_buffer_enter_filetype = vim.bo.filetype
vim.api.nvim_win_set_var(0, "neo_tree_settings_applied", true)
return
end
if vim.bo.filetype == "neo-tree-popup" then
vim.cmd([[
setlocal winhighlight=Normal:NeoTreeFloatNormal,FloatBorder:NeoTreeFloatBorder
setlocal nolist nospell nonumber norelativenumber
]])
events.fire_event(events.NEO_TREE_POPUP_BUFFER_ENTER)
last_buffer_enter_filetype = vim.bo.filetype
return
end
if last_buffer_enter_filetype == "neo-tree" then
events.fire_event(events.NEO_TREE_BUFFER_LEAVE)
end
if last_buffer_enter_filetype == "neo-tree-popup" then
events.fire_event(events.NEO_TREE_POPUP_BUFFER_LEAVE)
end
last_buffer_enter_filetype = vim.bo.filetype
-- there is nothing more we want to do with floating windows
if utils.is_floating() then
return
end
-- if vim is trying to open a dir, then we hijack it
if netrw.hijack() then
return
end
-- For all others, make sure another buffer is not hijacking our window
-- ..but not if the position is "current"
local prior_buf = vim.fn.bufnr("#")
if prior_buf < 1 then
return
end
local winid = vim.api.nvim_get_current_win()
local prior_type = vim.api.nvim_buf_get_option(prior_buf, "filetype")
if prior_type == "neo-tree" then
local success, position = pcall(vim.api.nvim_buf_get_var, prior_buf, "neo_tree_position")
if not success then
-- just bail out now, the rest of these lookups will probably fail too.
return
end
if position == "current" then
-- nothing to do here, files are supposed to open in same window
return
end
local current_tabid = vim.api.nvim_get_current_tabpage()
local neo_tree_tabid = vim.api.nvim_buf_get_var(prior_buf, "neo_tree_tabid")
if neo_tree_tabid ~= current_tabid then
-- This a new tab, so the alternate being neo-tree doesn't matter.
return
end
local neo_tree_winid = vim.api.nvim_buf_get_var(prior_buf, "neo_tree_winid")
local current_winid = vim.api.nvim_get_current_win()
if neo_tree_winid ~= current_winid then
-- This is not the neo-tree window, so the alternate being neo-tree doesn't matter.
return
end
local bufname = vim.api.nvim_buf_get_name(0)
log.debug("redirecting buffer " .. bufname .. " to new split")
vim.cmd("b#")
-- Using schedule at this point fixes problem with syntax
-- highlighting in the buffer. I also prevents errors with diagnostics
-- trying to work with the buffer as it's being closed.
vim.schedule(function()
-- try to delete the buffer, only because if it was new it would take
-- on options from the neo-tree window that are undesirable.
pcall(vim.cmd, "bdelete " .. bufname)
local fake_state = {
window = {
position = position,
},
}
utils.open_file(fake_state, bufname)
end)
end
end
M.win_enter_event = function()
local win_id = vim.api.nvim_get_current_win()
if utils.is_floating(win_id) then
return
end
-- if the new win is not a floating window, make sure all neo-tree floats are closed
manager.close_all("float")
if M.config.close_if_last_window then
local tabid = vim.api.nvim_get_current_tabpage()
local wins = utils.get_value(M, "config.prior_windows", {})[tabid]
local prior_exists = utils.truthy(wins)
local non_floating_wins = vim.tbl_filter(function(win)
return not utils.is_floating(win)
end, vim.api.nvim_tabpage_list_wins(tabid))
local win_count = #non_floating_wins
log.trace("checking if last window")
log.trace("prior window exists = ", prior_exists)
log.trace("win_count: ", win_count)
if prior_exists and win_count == 1 and vim.o.filetype == "neo-tree" then
local position = vim.api.nvim_buf_get_var(0, "neo_tree_position")
local source = vim.api.nvim_buf_get_var(0, "neo_tree_source")
if position ~= "current" then
-- close_if_last_window just doesn't make sense for a split style
log.trace("last window, closing")
local state = require("neo-tree.sources.manager").get_state(source)
if state == nil then
return
end
local mod = utils.get_opened_buffers()
log.debug("close_if_last_window, modified files found: ", vim.inspect(mod))
for filename, buf_info in pairs(mod) do
if buf_info.modified then
local buf_name, message
if vim.startswith(filename, "[No Name]#") then
buf_name = string.sub(filename, 11)
message = "Cannot close because an unnamed buffer is modified. Please save or discard this file."
else
buf_name = filename
message = "Cannot close because one of the files is modified. Please save or discard changes."
end
log.trace("close_if_last_window, showing unnamed modified buffer: ", filename)
vim.schedule(function()
log.warn(message)
vim.cmd("rightbelow vertical split")
vim.api.nvim_win_set_width(win_id, state.window.width or 40)
vim.cmd("b" .. buf_name)
end)
return
end
end
vim.cmd("q!")
return
end
end
end
if vim.o.filetype == "neo-tree" then
local _, position = pcall(vim.api.nvim_buf_get_var, 0, "neo_tree_position")
if position == "current" then
-- make sure the buffer wasn't moved to a new window
local neo_tree_winid = vim.api.nvim_buf_get_var(0, "neo_tree_winid")
local current_winid = vim.api.nvim_get_current_win()
local current_bufnr = vim.api.nvim_get_current_buf()
if neo_tree_winid ~= current_winid then
-- At this point we know that either the neo-tree window was split,
-- or the neo-tree buffer is being shown in another window for some other reason.
-- Sometime the split is just the first step in the process of opening somethig else,
-- so instead of fixing this right away, we add a short delay and check back again to see
-- if the buffer is still in this window.
local old_state = manager.get_state("filesystem", nil, neo_tree_winid)
vim.schedule(function()
local bufnr = vim.api.nvim_get_current_buf()
if bufnr ~= current_bufnr then
-- The neo-tree buffer was replaced with something else, so we don't need to do anything.
log.trace("neo-tree buffer replaced with something else - no further action required")
return
end
-- create a new tree for this window
local state = manager.get_state("filesystem", nil, current_winid)
state.path = old_state.path
state.current_position = "current"
local renderer = require("neo-tree.ui.renderer")
state.force_open_folders = renderer.get_expanded_nodes(old_state.tree)
require("neo-tree.sources.filesystem")._navigate_internal(state, nil, nil, nil, false)
end)
return
end
end
-- it's a neo-tree window, ignore
return
end
M.config.prior_windows = M.config.prior_windows or {}
local tabid = vim.api.nvim_get_current_tabpage()
local tab_windows = M.config.prior_windows[tabid]
if tab_windows == nil then
tab_windows = {}
M.config.prior_windows[tabid] = tab_windows
end
table.insert(tab_windows, win_id)
-- prune the history when it gets too big
if #tab_windows > 100 then
local new_array = {}
local win_count = #tab_windows
for i = 80, win_count do
table.insert(new_array, tab_windows[i])
end
M.config.prior_windows[tabid] = new_array
end
end
M.set_log_level = function(level)
log.set_level(level)
end
local function merge_global_components_config(components, config)
local indent_exists = false
local merged_components = {}
local do_merge
do_merge = function(component)
local name = component[1]
if type(name) == "string" then
if name == "indent" then
indent_exists = true
end
local merged = { name }
local global_config = config.default_component_configs[name]
if global_config then
for k, v in pairs(global_config) do
merged[k] = v
end
end
for k, v in pairs(component) do
merged[k] = v
end
if name == "container" then
for i, child in ipairs(component.content) do
merged.content[i] = do_merge(child)
end
end
return merged
else
log.error("component name is the wrong type", component)
end
end
for _, component in ipairs(components) do
local merged = do_merge(component)
table.insert(merged_components, merged)
end
-- If the indent component is not specified, then add it.
-- We do this because it used to be implicitly added, so we don't want to
-- break any existing configs.
if not indent_exists then
local indent = { "indent" }
for k, v in pairs(config.default_component_configs.indent or {}) do
indent[k] = v
end
table.insert(merged_components, 1, indent)
end
return merged_components
end
local merge_renderers = function(default_config, source_default_config, user_config)
-- This can't be a deep copy/merge. If a renderer is specified in the target it completely
-- replaces the base renderer.
if source_default_config == nil then
-- first override the default config global renderer with the user's global renderers
for name, renderer in pairs(user_config.renderers or {}) do
log.debug("overriding global renderer for " .. name)
default_config.renderers[name] = renderer
end
else
-- then override the global renderers with the source specific renderers
source_default_config.renderers = source_default_config.renderers or {}
for name, renderer in pairs(default_config.renderers or {}) do
if source_default_config.renderers[name] == nil then
log.debug("overriding source renderer for " .. name)
local r = {}
-- Only copy components that exist in the target source.
-- This alllows us to specify global renderers that include components from all sources,
-- even if some of those components are not universal
for _, value in ipairs(renderer) do
if value[1] and source_default_config.components[value[1]] ~= nil then
table.insert(r, value)
end
end
source_default_config.renderers[name] = r
end
end
-- if user sets renderers, completely wipe the default ones
local source_name = source_default_config.name
for name, _ in pairs(source_default_config.renderers) do
local user = utils.get_value(user_config, source_name .. ".renderers." .. name)
if user then
source_default_config.renderers[name] = nil
end
end
end
end
M.merge_config = function(user_config, is_auto_config)
local default_config = vim.deepcopy(defaults)
user_config = vim.deepcopy(user_config or {})
local migrations = require("neo-tree.setup.deprecations").migrate(user_config)
if #migrations > 0 then
-- defer to make sure it is the last message printed
vim.defer_fn(function()
vim.cmd(
"echohl WarningMsg | echo 'Some options have changed, please run `:Neotree migrations` to see the changes' | echohl NONE"
)
end, 50)
end
if user_config.log_level ~= nil then
M.set_log_level(user_config.log_level)
end
log.use_file(user_config.log_to_file, true)
log.debug("setup")
events.clear_all_events()
define_events()
-- Prevent accidentally opening another file in the neo-tree window.
events.subscribe({
event = events.VIM_BUFFER_ENTER,
handler = M.buffer_enter_event,
})
-- Setup autocmd for neo-tree BufLeave, to restore window settings.
-- This is set to happen just before leaving the window.
-- The patterns used should ensure it only runs in neo-tree windows where position = "current"
local augroup = vim.api.nvim_create_augroup("NeoTree_BufLeave", { clear = true })
local bufleave = function(data)
-- Vim patterns in autocmds are not quite precise enough
-- so we are doing a second stage filter in lua
local pattern = "neo%-tree [^ ]+ %[1%d%d%d%]"
if string.match(data.file, pattern) then
restore_local_window_settings()
end
end
vim.api.nvim_create_autocmd({ "BufWinLeave" }, {
group = augroup,
pattern = "neo-tree *",
callback = bufleave,
})
if user_config.event_handlers ~= nil then
for _, handler in ipairs(user_config.event_handlers) do
events.subscribe(handler)
end
end
highlights.setup()
-- used to either limit the sources that or loaded, or add extra external sources
local all_sources = {}
local all_source_names = {}
for _, source in ipairs(user_config.sources or default_config.sources) do
local parts = utils.split(source, ".")
local name = parts[#parts]
local is_internal_ns, is_external_ns = false, false
local module
if #parts == 1 then
-- might be a module name in the internal namespace
is_internal_ns, module = pcall(require, "neo-tree.sources." .. source)
end
if is_internal_ns then
name = module.name or name
all_sources[name] = "neo-tree.sources." .. name
else
-- fully qualified module name
-- or just a root level module name
is_external_ns, module = pcall(require, source)
if is_external_ns then
name = module.name or name
all_sources[name] = source
else
log.error("Source module not found", source)
name = nil
end
end
if name then
default_config[name] = module.default_config or default_config[name]
table.insert(all_source_names, name)
end
end
log.debug("Sources to load: ", vim.inspect(all_sources))
require("neo-tree.command.parser").setup(all_source_names)
-- setup the default values for all sources
normalize_mappings(default_config)
normalize_mappings(user_config)
merge_renderers(default_config, nil, user_config)
for source_name, mod_root in pairs(all_sources) do
local module = require(mod_root)
default_config[source_name] = default_config[source_name]
or {
renderers = {},
components = {},
}
local source_default_config = default_config[source_name]
source_default_config.components = module.components or require(mod_root .. ".components")
source_default_config.commands = module.commands or require(mod_root .. ".commands")
source_default_config.name = source_name
source_default_config.display_name = module.display_name or source_default_config.name
if user_config.use_default_mappings == false then
default_config.window.mappings = {}
source_default_config.window.mappings = {}
end
-- Make sure all the mappings are normalized so they will merge properly.
normalize_mappings(source_default_config)
normalize_mappings(user_config[source_name])
-- merge the global config with the source specific config
source_default_config.window = vim.tbl_deep_extend(
"force",
default_config.window or {},
source_default_config.window or {},
user_config.window or {}
)
merge_renderers(default_config, source_default_config, user_config)
--validate the window.position
local pos_key = source_name .. ".window.position"
local position = utils.get_value(user_config, pos_key, "left", true)
local valid_positions = {
left = true,
right = true,
top = true,
bottom = true,
float = true,
current = true,
}
if not valid_positions[position] then
log.error("Invalid value for ", pos_key, ": ", position)
user_config[source_name].window.position = "left"
end
end
--print(vim.inspect(default_config.filesystem))
-- Moving user_config.sources to user_config.orig_sources
user_config.orig_sources = user_config.sources and user_config.sources or {}
-- apply the users config
M.config = vim.tbl_deep_extend("force", default_config, user_config)
-- RE: 873, fixes issue with invalid source checking by overriding
-- source table with name table
-- Setting new "sources" to be the parsed names of the sources
M.config.sources = all_source_names
if ( M.config.source_selector.winbar or M.config.source_selector.statusline )
and M.config.source_selector.sources
and not user_config.default_source then
-- Set the default source to the head of these
-- This resolves some weirdness with the source selector having
-- a different "head" item than our current default.
-- Removing this line makes Neo-tree show the "filesystem"
-- source instead of whatever the first item in the config is.
-- Probably don't remove this unless you have a better fix for that
M.config.default_source = M.config.source_selector.sources[1].source
end
-- Check if the default source is not included in config.sources
-- log a warning and then "pick" the first in the sources list
local match = false
for _, source in ipairs(M.config.sources) do
if source == M.config.default_source then
match = true
break
end
end
if not match and M.config.default_source ~= "last" then
M.config.default_source = M.config.sources[1]
log.warn(string.format("Invalid default source found in configuration. Using first available source: %s", M.config.default_source))
end
if not M.config.enable_git_status then
M.config.git_status_async = false
end
-- Validate that the source_selector.sources are all available and if any
-- aren't, remove them
local source_selector_sources = {}
for _, ss_source in ipairs(M.config.source_selector.sources or {}) do
local source_match = false
for _, source in ipairs(M.config.sources) do
if ss_source.source == source then
source_match = true
break
end
end
if source_match then
table.insert(source_selector_sources, ss_source)
else
log.debug(string.format("Unable to locate Neo-tree extension %s", ss_source.source))
end
end
M.config.source_selector.sources = source_selector_sources
file_nesting.setup(M.config.nesting_rules)
for source_name, mod_root in pairs(all_sources) do
for name, rndr in pairs(M.config[source_name].renderers) do
M.config[source_name].renderers[name] = merge_global_components_config(rndr, M.config)
end
local module = require(mod_root)
if M.config.commands then
M.config[source_name].commands =
vim.tbl_extend("keep", M.config[source_name].commands or {}, M.config.commands)
end
manager.setup(source_name, M.config[source_name], M.config, module)
manager.redraw(source_name)
end
if M.config.auto_clean_after_session_restore then
require("neo-tree.ui.renderer").clean_invalid_neotree_buffers(false)
events.subscribe({
event = events.VIM_AFTER_SESSION_LOAD,
handler = function()
require("neo-tree.ui.renderer").clean_invalid_neotree_buffers(true)
end,
})
end
events.subscribe({
event = events.VIM_COLORSCHEME,
handler = highlights.setup,
id = "neo-tree-highlight",
})
events.subscribe({
event = events.VIM_WIN_ENTER,
handler = M.win_enter_event,
id = "neo-tree-win-enter",
})
--Dispose ourselves if the tab closes
events.subscribe({
event = events.VIM_TAB_CLOSED,
handler = function(args)
local tabnr = tonumber(args.afile)
log.debug("VIM_TAB_CLOSED: disposing state for tabnr", tabnr)
-- Internally we use tabids to track state but <afile> is tabnr of a tab that has already been
-- closed so there is no way to get its tabid. Instead dispose all tabs that are no longer valid.
-- Must be scheduled because nvim_tabpage_is_valid does not work inside TabClosed event callback.
vim.schedule_wrap(manager.dispose_invalid_tabs)()
end,
})
--Dispose ourselves if the tab closes
events.subscribe({
event = events.VIM_WIN_CLOSED,
handler = function(args)
local winid = tonumber(args.afile)
log.debug("VIM_WIN_CLOSED: disposing state for window", winid)
manager.dispose_window(winid)
end,
})
local rt = utils.get_value(M.config, "resize_timer_interval", 50, true)
require("neo-tree.ui.renderer").resize_timer_interval = rt
if M.config.enable_cursor_hijack then
hijack_cursor.setup()
end
return M.config
end
return M