From 716dd8f9cf1ff2b9cda03497025612ce3c366307 Mon Sep 17 00:00:00 2001 From: Steven Arcangeli Date: Sat, 28 Jan 2023 18:07:18 -0800 Subject: [PATCH] fix: unexpected behavior from BufReadPost autocmds --- lua/oil/init.lua | 39 +++++++++++++++++++++++---------------- lua/oil/util.lua | 24 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/lua/oil/init.lua b/lua/oil/init.lua index 1754d27..01ec2cf 100644 --- a/lua/oil/init.lua +++ b/lua/oil/init.lua @@ -587,24 +587,31 @@ local function load_oil_buffer(bufnr) keymap_util.set_keymaps("", config.keymaps, bufnr) end loading.set_loading(bufnr, true) + local winid = vim.api.nvim_get_current_win() local function finish(new_url) - if new_url ~= bufname then - if util.rename_buffer(bufnr, new_url) then - -- If the buffer was replaced then don't initialize it. It's dead. The replacement will - -- have BufReadCmd called for it - return + -- Since this was async, we may have left the window with this buffer. People often write + -- BufReadPre/Post autocmds with the expectation that the current window is the one that + -- contains the buffer. Let's then do our best to make sure that that assumption isn't violated. + winid = util.buf_get_win(bufnr, winid) or vim.api.nvim_get_current_win() + vim.api.nvim_win_call(winid, function() + if new_url ~= bufname then + if util.rename_buffer(bufnr, new_url) then + -- If the buffer was replaced then don't initialize it. It's dead. The replacement will + -- have BufReadCmd called for it + return + end + bufname = new_url end - bufname = new_url - end - if vim.endswith(bufname, "/") then - vim.cmd.doautocmd({ args = { "BufReadPre", bufname }, mods = { emsg_silent = true } }) - view.initialize(bufnr) - vim.cmd.doautocmd({ args = { "BufReadPost", bufname }, mods = { emsg_silent = true } }) - else - vim.bo[bufnr].buftype = "acwrite" - adapter.read_file(bufnr) - end - restore_alt_buf() + if vim.endswith(bufname, "/") then + vim.cmd.doautocmd({ args = { "BufReadPre", bufname }, mods = { emsg_silent = true } }) + view.initialize(bufnr) + vim.cmd.doautocmd({ args = { "BufReadPost", bufname }, mods = { emsg_silent = true } }) + else + vim.bo[bufnr].buftype = "acwrite" + adapter.read_file(bufnr) + end + restore_alt_buf() + end) end adapter.normalize_url(bufname, finish) diff --git a/lua/oil/util.lua b/lua/oil/util.lua index 5aae2cb..d6bad47 100644 --- a/lua/oil/util.lua +++ b/lua/oil/util.lua @@ -525,4 +525,28 @@ M.get_preview_win = function() end end +---@param bufnr integer +---@param preferred_win nil|integer +---@return nil|integer +M.buf_get_win = function(bufnr, preferred_win) + if + preferred_win + and vim.api.nvim_win_is_valid(preferred_win) + and vim.api.nvim_win_get_buf(preferred_win) == bufnr + then + return preferred_win + end + for _, winid in ipairs(vim.api.nvim_tabpage_list_wins(0)) do + if vim.api.nvim_win_is_valid(winid) and vim.api.nvim_win_get_buf(winid) == bufnr then + return winid + end + end + for _, winid in ipairs(vim.api.nvim_list_wins()) do + if vim.api.nvim_win_is_valid(winid) and vim.api.nvim_win_get_buf(winid) == bufnr then + return winid + end + end + return nil +end + return M