From 540c811cb24fed507445d6e2f2dc4c6dd44788ee Mon Sep 17 00:00:00 2001 From: kiyan Date: Thu, 26 May 2022 13:37:50 +0200 Subject: [PATCH] fix(open file): do not trigger buf enter event when setting target win Fixes #1288 Also starts a refactoring of the open-file code, to make it easier to debug and improve. --- lua/nvim-tree/actions/open-file.lua | 167 ++++++++++++++++------------ 1 file changed, 96 insertions(+), 71 deletions(-) diff --git a/lua/nvim-tree/actions/open-file.lua b/lua/nvim-tree/actions/open-file.lua index b2f7315c..3e53d857 100644 --- a/lua/nvim-tree/actions/open-file.lua +++ b/lua/nvim-tree/actions/open-file.lua @@ -135,21 +135,23 @@ local function open_file_in_tab(filename) vim.cmd("tabe " .. vim.fn.fnameescape(filename)) end -function M.fn(mode, filename) - if mode == "tabnew" then - open_file_in_tab(filename) - return +local function on_preview(buf_loaded) + if not buf_loaded then + vim.bo.bufhidden = "delete" + + api.nvim_create_autocmd({ "TextChanged", "TextChangedI" }, { + group = api.nvim_create_augroup("RemoveBufHidden", {}), + buffer = api.nvim_get_current_buf(), + callback = function() + vim.bo.bufhidden = "" + end, + once = true, + }) end + view.focus() +end - if mode == "edit_in_place" then - require("nvim-tree.view").abandon_current_window() - vim.cmd("edit " .. vim.fn.fnameescape(filename)) - return - end - - local tabpage = api.nvim_get_current_tabpage() - local win_ids = api.nvim_tabpage_list_wins(tabpage) - +local function get_target_winid(mode) local target_winid if not M.window_picker.enable or mode == "edit_no_picker" then target_winid = lib.target_winid @@ -164,64 +166,99 @@ function M.fn(mode, filename) if target_winid == -1 then target_winid = lib.target_winid end + return target_winid +end +-- This is only to avoid the BufEnter for nvim-tree to trigger +-- which would cause find-file to run on an invalid file. +local function set_current_win_no_autocmd(winid) + vim.cmd "set ei=BufEnter" + api.nvim_set_current_win(winid) + vim.cmd 'set ei=""' +end + +local function when_not_found(filename, mode, win_ids) + local target_winid = get_target_winid(mode) local do_split = mode == "split" or mode == "vsplit" local vertical = mode ~= "split" - -- Check if file is already loaded in a buffer - local buf_loaded = false - for _, buf_id in ipairs(api.nvim_list_bufs()) do - if api.nvim_buf_is_loaded(buf_id) and filename == api.nvim_buf_get_name(buf_id) then - buf_loaded = true - break + -- Target is invalid or window does not exist in current tabpage: create new window + if not target_winid or not vim.tbl_contains(win_ids, target_winid) then + local split_cmd = get_split_cmd() + local splitside = view.is_vertical() and "vsp" or "sp" + vim.cmd(split_cmd .. " " .. splitside) + target_winid = api.nvim_get_current_win() + lib.target_winid = target_winid + + -- No need to split, as we created a new window. + do_split = false + elseif not vim.o.hidden then + -- If `hidden` is not enabled, check if buffer in target window is + -- modified, and create new split if it is. + local target_bufid = api.nvim_win_get_buf(target_winid) + if api.nvim_buf_get_option(target_bufid, "modified") then + do_split = true end end - -- Check if filename is already open in a window - local found = false + local fname = vim.fn.fnameescape(filename) + + local cmd + if do_split or #api.nvim_list_wins() == 1 then + cmd = string.format("%ssplit %s", vertical and "vertical " or "", fname) + else + cmd = string.format("edit %s", fname) + end + + set_current_win_no_autocmd(target_winid) + pcall(vim.cmd, cmd) + lib.set_target_win() +end + +local function is_already_open(filename, win_ids) for _, id in ipairs(win_ids) do if filename == api.nvim_buf_get_name(api.nvim_win_get_buf(id)) then - if mode == "preview" then - return - end - found = true api.nvim_set_current_win(id) - break + return true end end + return false +end + +local function is_already_loaded(filename) + for _, buf_id in ipairs(api.nvim_list_bufs()) do + if api.nvim_buf_is_loaded(buf_id) and filename == api.nvim_buf_get_name(buf_id) then + return true + end + end + return false +end + +local function edit_in_current_buf(filename) + require("nvim-tree.view").abandon_current_window() + vim.cmd("edit " .. vim.fn.fnameescape(filename)) +end + +function M.fn(mode, filename) + if mode == "tabnew" then + return open_file_in_tab(filename) + end + + if mode == "edit_in_place" then + return edit_in_current_buf(filename) + end + + local tabpage = api.nvim_get_current_tabpage() + local win_ids = api.nvim_tabpage_list_wins(tabpage) + + local found = is_already_open(filename, win_ids) + if found and mode == "preview" then + return + end + if not found then - if not target_winid or not vim.tbl_contains(win_ids, target_winid) then - -- Target is invalid, or window does not exist in current tabpage: create - -- new window - local split_cmd = get_split_cmd() - local splitside = view.is_vertical() and "vsp" or "sp" - vim.cmd(split_cmd .. " " .. splitside) - target_winid = api.nvim_get_current_win() - lib.target_winid = target_winid - - -- No need to split, as we created a new window. - do_split = false - elseif not vim.o.hidden then - -- If `hidden` is not enabled, check if buffer in target window is - -- modified, and create new split if it is. - local target_bufid = api.nvim_win_get_buf(target_winid) - if api.nvim_buf_get_option(target_bufid, "modified") then - do_split = true - end - end - - local cmd - if do_split or #api.nvim_list_wins() == 1 then - cmd = string.format("%ssplit ", vertical and "vertical " or "") - else - cmd = "edit " - end - - cmd = cmd .. vim.fn.fnameescape(filename) - api.nvim_set_current_win(target_winid) - pcall(vim.cmd, cmd) - lib.set_target_win() + when_not_found(filename, mode, win_ids) end if M.resize_window then @@ -229,20 +266,8 @@ function M.fn(mode, filename) end if mode == "preview" then - if not buf_loaded then - vim.bo.bufhidden = "delete" - - api.nvim_create_autocmd({ "TextChanged", "TextChangedI" }, { - group = api.nvim_create_augroup("RemoveBufHidden", {}), - buffer = api.nvim_get_current_buf(), - callback = function() - vim.bo.bufhidden = "" - end, - once = true, - }) - end - view.focus() - return + local buf_loaded = is_already_loaded(filename) + return on_preview(buf_loaded) end if M.quit_on_open then