diff --git a/Dockerfile b/Dockerfile index 9ac4c08f8..e8072a66c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ RUN apt install -y git ninja-build gettext libtool libtool-bin autoconf \ # install neovim RUN git clone https://github.com/neovim/neovim -RUN cd neovim && make CMAKE_BUILD_TYPE=RelWithDebInfo && make install +RUN cd neovim && git checkout release-0.11 && make CMAKE_BUILD_TYPE=RelWithDebInfo && make install # install required plugins ARG PLUG_DIR="root/.local/share/nvim/site/pack/packer/start" diff --git a/lua/neo-tree/setup/init.lua b/lua/neo-tree/setup/init.lua index d7bdf02cb..a6c53f29f 100644 --- a/lua/neo-tree/setup/init.lua +++ b/lua/neo-tree/setup/init.lua @@ -268,7 +268,6 @@ M.win_enter_event = function() -- 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] @@ -740,6 +739,94 @@ M.merge_config = function(user_config) id = "neo-tree-win-enter", }) + vim.api.nvim_create_autocmd("WinClosed", { + callback = function(args) + local closing_win = tonumber(args.match) + if utils.is_floating(closing_win) then + return + end + + local neotree_sidebar_exists = false + for _, win in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + if win ~= closing_win then + local buf = vim.api.nvim_win_get_buf(win) + local neotree_pos = vim.b[buf].neo_tree_position + if not utils.is_floating(win) and neotree_pos then + neotree_sidebar_exists = true + if neotree_pos == "left" then + left_neotree = win + elseif neotree_pos == "right" then + right_neotree = win + end + end + end + end + + if not neotree_sidebar_exists then + return + end + + -- When we have an open sidebar and the other non-floating windows are all closed, prevent neo-tree from expanding. + local left_neotree, right_neotree, bottom_neotree, top_neotree + local floating_wins = {} + local neotree_wins = {} + for _, win in ipairs(vim.api.nvim_list_wins()) do + local buf = vim.api.nvim_win_get_buf(win) + local neotree_pos = vim.b[buf].neo_tree_position + if utils.is_floating(win) then + table.insert(floating_wins, win) + end + if neotree_pos then + table.insert(neotree_wins, win) + end + end + + -- skip buffers shown in floating windows and edgy windows + local skip = {} + for _, win in pairs(floating_wins) do + local buf = vim.api.nvim_win_get_buf(win) + skip[buf] = buf + end + for _, win in pairs(neotree_wins) do + local buf = vim.api.nvim_win_get_buf(win) + skip[buf] = buf + end + + local bufs = {} + for _, buf in ipairs(vim.api.nvim_list_bufs()) do + if not skip[buf] then + table.insert(bufs, buf) + end + end + + -- sort by last enter time + table.sort(bufs, function(a, b) + return (vim.b[a].neotree_enter or 0) > (vim.b[b].neotree_enter or 0) + end) + + local direction + if left_neotree then + direction = "vertical rightbelow" + elseif right_neotree then + direction = "vertical leftabove" + elseif bottom_neotree then + direction = "topleft" + elseif top_neotree then + direction = "botright" + end + local edit_cmd = bufs[1] and "sb " .. bufs[1] or "new" + vim.cmd(([[%s %s]]):format(direction, edit_cmd)) + end, + }) + + local enter_tick = 1 + vim.api.nvim_create_autocmd("WinEnter", { + callback = function(args) + vim.b[args.buf].neotree_enter = enter_tick + enter_tick = enter_tick + 1 + end, + }) + --Dispose ourselves if the tab closes events.subscribe({ event = events.VIM_TAB_CLOSED, diff --git a/lua/neo-tree/utils/init.lua b/lua/neo-tree/utils/init.lua index 854851ee4..951909cb7 100644 --- a/lua/neo-tree/utils/init.lua +++ b/lua/neo-tree/utils/init.lua @@ -754,9 +754,9 @@ end ---Open file in the appropriate window. ---@param state table The state of the source ----@param path string The file to open +---@param path string? The file to open ---@param open_cmd string? The vimcommand to use to open the file ----@param bufnr number|nil The buffer number to open +---@param bufnr integer? The buffer number to open M.open_file = function(state, path, open_cmd, bufnr) open_cmd = open_cmd or "edit" -- If the file is already open, switch to it. @@ -774,65 +774,67 @@ M.open_file = function(state, path, open_cmd, bufnr) end end - if M.truthy(path) then - local relative = require("neo-tree").config.open_files_using_relative_paths - local escaped_path = M.escape_path_for_cmd(relative and vim.fn.fnamemodify(path, ":.") or path) - local bufnr_or_path = bufnr or escaped_path - local events = require("neo-tree.events") - local result = true - local err = nil - local event_result = events.fire_event(events.FILE_OPEN_REQUESTED, { - state = state, - path = path, - open_cmd = open_cmd, - bufnr = bufnr, - }) or {} - if event_result.handled then - events.fire_event(events.FILE_OPENED, path) - return - end - if state.current_position == "current" then + if not path or not M.truthy(path) then + return + end + + local relative = require("neo-tree").config.open_files_using_relative_paths + local escaped_path = M.escape_path_for_cmd(relative and vim.fn.fnamemodify(path, ":.") or path) + local bufnr_or_path = bufnr or escaped_path + local events = require("neo-tree.events") + local result = true + local err = nil + local event_result = events.fire_event(events.FILE_OPEN_REQUESTED, { + state = state, + path = path, + open_cmd = open_cmd, + bufnr = bufnr, + }) or {} + if event_result.handled then + events.fire_event(events.FILE_OPENED, path) + return + end + if state.current_position == "current" then + ---@diagnostic disable-next-line: param-type-mismatch + result, err = pcall(vim.cmd, open_cmd .. " " .. bufnr_or_path) + else + local winid, is_neo_tree_window = M.get_appropriate_window(state) + vim.api.nvim_set_current_win(winid) + -- TODO: make this configurable, see issue #43 + if is_neo_tree_window then + local width = vim.api.nvim_win_get_width(0) + if width == vim.o.columns then + -- Neo-tree must be the only window, restore it's status as a sidebar + width = M.get_value(state, "window.width", 40, false) + width = M.resolve_width(width) + end + result, err = M.force_new_split(state.current_position, escaped_path) + vim.api.nvim_win_set_width(winid, width) + else ---@diagnostic disable-next-line: param-type-mismatch result, err = pcall(vim.cmd, open_cmd .. " " .. bufnr_or_path) - else - local winid, is_neo_tree_window = M.get_appropriate_window(state) - vim.api.nvim_set_current_win(winid) - -- TODO: make this configurable, see issue #43 - if is_neo_tree_window then - local width = vim.api.nvim_win_get_width(0) - if width == vim.o.columns then - -- Neo-tree must be the only window, restore it's status as a sidebar - width = M.get_value(state, "window.width", 40, false) - width = M.resolve_width(width) - end - result, err = M.force_new_split(state.current_position, escaped_path) - vim.api.nvim_win_set_width(winid, width) - else - ---@diagnostic disable-next-line: param-type-mismatch - result, err = pcall(vim.cmd, open_cmd .. " " .. bufnr_or_path) - end - end - if not result and string.find(err or "", "winfixbuf") and M.is_winfixbuf() then - local winid, is_neo_tree_window = M.get_appropriate_window(state, true) - -- Rescan window list to find a window that is not winfixbuf. - -- If found, retry executing command in that window, - -- otherwise, all windows are either neo-tree or winfixbuf so we make a new split. - if not is_neo_tree_window and not M.is_winfixbuf(winid) then - vim.api.nvim_set_current_win(winid) - ---@diagnostic disable-next-line: param-type-mismatch - result, err = pcall(vim.cmd, open_cmd .. " " .. bufnr_or_path) - else - result, err = M.force_new_split(state.current_position, escaped_path) - end end - if result or err == "Vim(edit):E325: ATTENTION" then - -- fixes #321 - vim.bo[0].buflisted = true - events.fire_event(events.FILE_OPENED, path) + end + if not result and string.find(err or "", "winfixbuf") and M.is_winfixbuf() then + local winid, is_neo_tree_window = M.get_appropriate_window(state, true) + -- Rescan window list to find a window that is not winfixbuf. + -- If found, retry executing command in that window, + -- otherwise, all windows are either neo-tree or winfixbuf so we make a new split. + if not is_neo_tree_window and not M.is_winfixbuf(winid) then + vim.api.nvim_set_current_win(winid) + ---@diagnostic disable-next-line: param-type-mismatch + result, err = pcall(vim.cmd, open_cmd .. " " .. bufnr_or_path) else - log.error("Error opening file:", err) + result, err = M.force_new_split(state.current_position, escaped_path) end end + if result or err == "Vim(edit):E325: ATTENTION" then + -- fixes #321 + vim.bo[0].buflisted = true + events.fire_event(events.FILE_OPENED, path) + else + log.error("Error opening file:", err) + end end M.reduce = function(list, memo, func)