Skip to content

Commit 544f6af

Browse files
committed
preserve layout when non-neotree splits all close
1 parent 73d6337 commit 544f6af

File tree

3 files changed

+146
-57
lines changed

3 files changed

+146
-57
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ RUN apt install -y git ninja-build gettext libtool libtool-bin autoconf \
77

88
# install neovim
99
RUN git clone https://github.com/neovim/neovim
10-
RUN cd neovim && make CMAKE_BUILD_TYPE=RelWithDebInfo && make install
10+
RUN cd neovim && git checkout release-0.11 && make CMAKE_BUILD_TYPE=RelWithDebInfo && make install
1111

1212
# install required plugins
1313
ARG PLUG_DIR="root/.local/share/nvim/site/pack/packer/start"

lua/neo-tree/setup/init.lua

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,6 @@ M.win_enter_event = function()
268268

269269
-- if the new win is not a floating window, make sure all neo-tree floats are closed
270270
manager.close_all("float")
271-
272271
if M.config.close_if_last_window then
273272
local tabid = vim.api.nvim_get_current_tabpage()
274273
local wins = utils.get_value(M, "config.prior_windows", {})[tabid]
@@ -740,6 +739,94 @@ M.merge_config = function(user_config)
740739
id = "neo-tree-win-enter",
741740
})
742741

742+
vim.api.nvim_create_autocmd("WinClosed", {
743+
callback = function(args)
744+
local closing_win = tonumber(args.match)
745+
if utils.is_floating(closing_win) then
746+
return
747+
end
748+
749+
local neotree_sidebar_exists = false
750+
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
751+
if win ~= closing_win then
752+
local buf = vim.api.nvim_win_get_buf(win)
753+
local neotree_pos = vim.b[buf].neo_tree_position
754+
if not utils.is_floating(win) and neotree_pos then
755+
neotree_sidebar_exists = true
756+
if neotree_pos == "left" then
757+
left_neotree = win
758+
elseif neotree_pos == "right" then
759+
right_neotree = win
760+
end
761+
end
762+
end
763+
end
764+
765+
if not neotree_sidebar_exists then
766+
return
767+
end
768+
769+
-- When we have an open sidebar and the other non-floating windows are all closed, prevent neo-tree from expanding.
770+
local left_neotree, right_neotree, bottom_neotree, top_neotree
771+
local floating_wins = {}
772+
local neotree_wins = {}
773+
for _, win in ipairs(vim.api.nvim_list_wins()) do
774+
local buf = vim.api.nvim_win_get_buf(win)
775+
local neotree_pos = vim.b[buf].neo_tree_position
776+
if utils.is_floating(win) then
777+
table.insert(floating_wins, win)
778+
end
779+
if neotree_pos then
780+
table.insert(neotree_wins, win)
781+
end
782+
end
783+
784+
-- skip buffers shown in floating windows and edgy windows
785+
local skip = {}
786+
for _, win in pairs(floating_wins) do
787+
local buf = vim.api.nvim_win_get_buf(win)
788+
skip[buf] = buf
789+
end
790+
for _, win in pairs(neotree_wins) do
791+
local buf = vim.api.nvim_win_get_buf(win)
792+
skip[buf] = buf
793+
end
794+
795+
local bufs = {}
796+
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
797+
if not skip[buf] then
798+
table.insert(bufs, buf)
799+
end
800+
end
801+
802+
-- sort by last enter time
803+
table.sort(bufs, function(a, b)
804+
return (vim.b[a].neotree_enter or 0) > (vim.b[b].neotree_enter or 0)
805+
end)
806+
807+
local direction
808+
if left_neotree then
809+
direction = "vertical rightbelow"
810+
elseif right_neotree then
811+
direction = "vertical leftabove"
812+
elseif bottom_neotree then
813+
direction = "topleft"
814+
elseif top_neotree then
815+
direction = "botright"
816+
end
817+
local edit_cmd = bufs[1] and "sb " .. bufs[1] or "new"
818+
vim.cmd(([[%s %s]]):format(direction, edit_cmd))
819+
end,
820+
})
821+
822+
local enter_tick = 1
823+
vim.api.nvim_create_autocmd("WinEnter", {
824+
callback = function(args)
825+
vim.b[args.buf].neotree_enter = enter_tick
826+
enter_tick = enter_tick + 1
827+
end,
828+
})
829+
743830
--Dispose ourselves if the tab closes
744831
events.subscribe({
745832
event = events.VIM_TAB_CLOSED,

lua/neo-tree/utils/init.lua

Lines changed: 57 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -754,9 +754,9 @@ end
754754

755755
---Open file in the appropriate window.
756756
---@param state table The state of the source
757-
---@param path string The file to open
757+
---@param path string? The file to open
758758
---@param open_cmd string? The vimcommand to use to open the file
759-
---@param bufnr number|nil The buffer number to open
759+
---@param bufnr integer? The buffer number to open
760760
M.open_file = function(state, path, open_cmd, bufnr)
761761
open_cmd = open_cmd or "edit"
762762
-- If the file is already open, switch to it.
@@ -774,65 +774,67 @@ M.open_file = function(state, path, open_cmd, bufnr)
774774
end
775775
end
776776

777-
if M.truthy(path) then
778-
local relative = require("neo-tree").config.open_files_using_relative_paths
779-
local escaped_path = M.escape_path_for_cmd(relative and vim.fn.fnamemodify(path, ":.") or path)
780-
local bufnr_or_path = bufnr or escaped_path
781-
local events = require("neo-tree.events")
782-
local result = true
783-
local err = nil
784-
local event_result = events.fire_event(events.FILE_OPEN_REQUESTED, {
785-
state = state,
786-
path = path,
787-
open_cmd = open_cmd,
788-
bufnr = bufnr,
789-
}) or {}
790-
if event_result.handled then
791-
events.fire_event(events.FILE_OPENED, path)
792-
return
793-
end
794-
if state.current_position == "current" then
777+
if not path or not M.truthy(path) then
778+
return
779+
end
780+
781+
local relative = require("neo-tree").config.open_files_using_relative_paths
782+
local escaped_path = M.escape_path_for_cmd(relative and vim.fn.fnamemodify(path, ":.") or path)
783+
local bufnr_or_path = bufnr or escaped_path
784+
local events = require("neo-tree.events")
785+
local result = true
786+
local err = nil
787+
local event_result = events.fire_event(events.FILE_OPEN_REQUESTED, {
788+
state = state,
789+
path = path,
790+
open_cmd = open_cmd,
791+
bufnr = bufnr,
792+
}) or {}
793+
if event_result.handled then
794+
events.fire_event(events.FILE_OPENED, path)
795+
return
796+
end
797+
if state.current_position == "current" then
798+
---@diagnostic disable-next-line: param-type-mismatch
799+
result, err = pcall(vim.cmd, open_cmd .. " " .. bufnr_or_path)
800+
else
801+
local winid, is_neo_tree_window = M.get_appropriate_window(state)
802+
vim.api.nvim_set_current_win(winid)
803+
-- TODO: make this configurable, see issue #43
804+
if is_neo_tree_window then
805+
local width = vim.api.nvim_win_get_width(0)
806+
if width == vim.o.columns then
807+
-- Neo-tree must be the only window, restore it's status as a sidebar
808+
width = M.get_value(state, "window.width", 40, false)
809+
width = M.resolve_width(width)
810+
end
811+
result, err = M.force_new_split(state.current_position, escaped_path)
812+
vim.api.nvim_win_set_width(winid, width)
813+
else
795814
---@diagnostic disable-next-line: param-type-mismatch
796815
result, err = pcall(vim.cmd, open_cmd .. " " .. bufnr_or_path)
797-
else
798-
local winid, is_neo_tree_window = M.get_appropriate_window(state)
799-
vim.api.nvim_set_current_win(winid)
800-
-- TODO: make this configurable, see issue #43
801-
if is_neo_tree_window then
802-
local width = vim.api.nvim_win_get_width(0)
803-
if width == vim.o.columns then
804-
-- Neo-tree must be the only window, restore it's status as a sidebar
805-
width = M.get_value(state, "window.width", 40, false)
806-
width = M.resolve_width(width)
807-
end
808-
result, err = M.force_new_split(state.current_position, escaped_path)
809-
vim.api.nvim_win_set_width(winid, width)
810-
else
811-
---@diagnostic disable-next-line: param-type-mismatch
812-
result, err = pcall(vim.cmd, open_cmd .. " " .. bufnr_or_path)
813-
end
814-
end
815-
if not result and string.find(err or "", "winfixbuf") and M.is_winfixbuf() then
816-
local winid, is_neo_tree_window = M.get_appropriate_window(state, true)
817-
-- Rescan window list to find a window that is not winfixbuf.
818-
-- If found, retry executing command in that window,
819-
-- otherwise, all windows are either neo-tree or winfixbuf so we make a new split.
820-
if not is_neo_tree_window and not M.is_winfixbuf(winid) then
821-
vim.api.nvim_set_current_win(winid)
822-
---@diagnostic disable-next-line: param-type-mismatch
823-
result, err = pcall(vim.cmd, open_cmd .. " " .. bufnr_or_path)
824-
else
825-
result, err = M.force_new_split(state.current_position, escaped_path)
826-
end
827816
end
828-
if result or err == "Vim(edit):E325: ATTENTION" then
829-
-- fixes #321
830-
vim.bo[0].buflisted = true
831-
events.fire_event(events.FILE_OPENED, path)
817+
end
818+
if not result and string.find(err or "", "winfixbuf") and M.is_winfixbuf() then
819+
local winid, is_neo_tree_window = M.get_appropriate_window(state, true)
820+
-- Rescan window list to find a window that is not winfixbuf.
821+
-- If found, retry executing command in that window,
822+
-- otherwise, all windows are either neo-tree or winfixbuf so we make a new split.
823+
if not is_neo_tree_window and not M.is_winfixbuf(winid) then
824+
vim.api.nvim_set_current_win(winid)
825+
---@diagnostic disable-next-line: param-type-mismatch
826+
result, err = pcall(vim.cmd, open_cmd .. " " .. bufnr_or_path)
832827
else
833-
log.error("Error opening file:", err)
828+
result, err = M.force_new_split(state.current_position, escaped_path)
834829
end
835830
end
831+
if result or err == "Vim(edit):E325: ATTENTION" then
832+
-- fixes #321
833+
vim.bo[0].buflisted = true
834+
events.fire_event(events.FILE_OPENED, path)
835+
else
836+
log.error("Error opening file:", err)
837+
end
836838
end
837839

838840
M.reduce = function(list, memo, func)

0 commit comments

Comments
 (0)