Skip to content

Commit 8e2c3d8

Browse files
committed
preserve layout when non-neotree splits all close
1 parent f14ac20 commit 8e2c3d8

File tree

3 files changed

+146
-56
lines changed

3 files changed

+146
-56
lines changed

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ RUN apk update && apk add --no-cache \
1010
gettext-tiny-dev \
1111
git
1212

13-
# Install neovim
14-
RUN git clone --depth=1 https://github.com/neovim/neovim --branch release-0.10
13+
# install neovim
14+
RUN git clone https://github.com/neovim/neovim
1515
RUN cd neovim && make CMAKE_BUILD_TYPE=RelWithDebInfo && make install
1616

1717
# --- Final Stage ---

lua/neo-tree/setup/init.lua

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -671,6 +671,94 @@ M.merge_config = function(user_config)
671671
id = "neo-tree-win-enter",
672672
})
673673

674+
vim.api.nvim_create_autocmd("WinClosed", {
675+
callback = function(args)
676+
local closing_win = tonumber(args.match)
677+
if utils.is_floating(closing_win) then
678+
return
679+
end
680+
681+
local neotree_sidebar_exists = false
682+
for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do
683+
if win ~= closing_win then
684+
local buf = vim.api.nvim_win_get_buf(win)
685+
local neotree_pos = vim.b[buf].neo_tree_position
686+
if not utils.is_floating(win) and neotree_pos then
687+
neotree_sidebar_exists = true
688+
if neotree_pos == "left" then
689+
left_neotree = win
690+
elseif neotree_pos == "right" then
691+
right_neotree = win
692+
end
693+
end
694+
end
695+
end
696+
697+
if not neotree_sidebar_exists then
698+
return
699+
end
700+
701+
-- When we have an open sidebar and the other non-floating windows are all closed, prevent neo-tree from expanding.
702+
local left_neotree, right_neotree, bottom_neotree, top_neotree
703+
local floating_wins = {}
704+
local neotree_wins = {}
705+
for _, win in ipairs(vim.api.nvim_list_wins()) do
706+
local buf = vim.api.nvim_win_get_buf(win)
707+
local neotree_pos = vim.b[buf].neo_tree_position
708+
if utils.is_floating(win) then
709+
table.insert(floating_wins, win)
710+
end
711+
if neotree_pos then
712+
table.insert(neotree_wins, win)
713+
end
714+
end
715+
716+
-- skip buffers shown in floating windows and edgy windows
717+
local skip = {}
718+
for _, win in pairs(floating_wins) do
719+
local buf = vim.api.nvim_win_get_buf(win)
720+
skip[buf] = buf
721+
end
722+
for _, win in pairs(neotree_wins) do
723+
local buf = vim.api.nvim_win_get_buf(win)
724+
skip[buf] = buf
725+
end
726+
727+
local bufs = {}
728+
for _, buf in ipairs(vim.api.nvim_list_bufs()) do
729+
if not skip[buf] then
730+
table.insert(bufs, buf)
731+
end
732+
end
733+
734+
-- sort by last enter time
735+
table.sort(bufs, function(a, b)
736+
return (vim.b[a].neotree_enter or 0) > (vim.b[b].neotree_enter or 0)
737+
end)
738+
739+
local direction
740+
if left_neotree then
741+
direction = "vertical rightbelow"
742+
elseif right_neotree then
743+
direction = "vertical leftabove"
744+
elseif bottom_neotree then
745+
direction = "topleft"
746+
elseif top_neotree then
747+
direction = "botright"
748+
end
749+
local edit_cmd = bufs[1] and "sb " .. bufs[1] or "new"
750+
vim.cmd(([[%s %s]]):format(direction, edit_cmd))
751+
end,
752+
})
753+
754+
local enter_tick = 1
755+
vim.api.nvim_create_autocmd("WinEnter", {
756+
callback = function(args)
757+
vim.b[args.buf].neotree_enter = enter_tick
758+
enter_tick = enter_tick + 1
759+
end,
760+
})
761+
674762
--Dispose ourselves if the tab closes
675763
events.subscribe({
676764
event = events.VIM_TAB_CLOSED,

lua/neo-tree/utils/init.lua

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ end
765765
---@param state neotree.State
766766
---@param path string The file to open
767767
---@param open_cmd string? The vimcommand to use to open the file
768-
---@param bufnr number|nil The buffer number to open
768+
---@param bufnr integer? The buffer number to open
769769
M.open_file = function(state, path, open_cmd, bufnr)
770770
open_cmd = open_cmd or "edit"
771771
-- If the file is already open, switch to it.
@@ -783,65 +783,67 @@ M.open_file = function(state, path, open_cmd, bufnr)
783783
end
784784
end
785785

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

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

0 commit comments

Comments
 (0)