diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-04-16 20:57:01 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-16 20:57:01 +0800 |
commit | 5cfdaaaeac0f53a621696d8eb6b5a3ba90438c98 (patch) | |
tree | 8d058733804bed0990c1a8e6836663f7b2460d5d | |
parent | 2fc2343728831d890a043def5d9d714947737cf6 (diff) | |
download | rneovim-5cfdaaaeac0f53a621696d8eb6b5a3ba90438c98.tar.gz rneovim-5cfdaaaeac0f53a621696d8eb6b5a3ba90438c98.tar.bz2 rneovim-5cfdaaaeac0f53a621696d8eb6b5a3ba90438c98.zip |
fix(api): ignore 'autochdir' when renaming other buf (#28376)
Problem: Renaming non-current buffer changes working directory when
'autochdir' is set.
Solution: Temporarily disable 'autochdir'. Add more tests for the
win_set_buf change.
-rw-r--r-- | src/nvim/api/buffer.c | 12 | ||||
-rw-r--r-- | src/nvim/autocmd.c | 2 | ||||
-rw-r--r-- | src/nvim/window.c | 15 | ||||
-rw-r--r-- | test/functional/api/buffer_spec.lua | 31 | ||||
-rw-r--r-- | test/functional/api/window_spec.lua | 99 |
5 files changed, 130 insertions, 29 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index b32159dc96..452ba49e04 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -39,6 +39,7 @@ #include "nvim/memory_defs.h" #include "nvim/move.h" #include "nvim/ops.h" +#include "nvim/option_vars.h" #include "nvim/pos_defs.h" #include "nvim/state_defs.h" #include "nvim/types_defs.h" @@ -984,12 +985,23 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err) try_start(); + const bool is_curbuf = buf == curbuf; + const int save_acd = p_acd; + if (!is_curbuf) { + // Temporarily disable 'autochdir' when setting file name for another buffer. + p_acd = false; + } + // Using aucmd_*: autocommands will be executed by rename_buffer aco_save_T aco; aucmd_prepbuf(&aco, buf); int ren_ret = rename_buffer(name.data); aucmd_restbuf(&aco); + if (!is_curbuf) { + p_acd = save_acd; + } + if (try_end(err)) { return; } diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index e9db4abf9b..c5d81d4cd2 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -1340,7 +1340,7 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf) win_config_float(auc_win, auc_win->w_config); } // Prevent chdir() call in win_enter_ext(), through do_autochdir() - int save_acd = p_acd; + const int save_acd = p_acd; p_acd = false; // no redrawing and don't set the window title RedrawingDisabled++; diff --git a/src/nvim/window.c b/src/nvim/window.c index 85ed73bd6d..ea879d450b 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -752,15 +752,20 @@ void win_set_buf(win_T *win, buf_T *buf, Error *err) goto cleanup; } - // temporarily disable 'autochdir' when using win_set_buf - // on non-current window - int save_acd = p_acd; + try_start(); + + const int save_acd = p_acd; if (!switchwin.sw_same_win) { + // Temporarily disable 'autochdir' when setting buffer in another window. p_acd = false; } - try_start(); + int result = do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0); - p_acd = save_acd; + + if (!switchwin.sw_same_win) { + p_acd = save_acd; + } + if (!try_end(err) && result == FAIL) { api_set_error(err, kErrorTypeException, diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index ec5c046878..12b2c43158 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -2048,6 +2048,37 @@ describe('api/buf', function() eq(1, fn.filereadable(new_name)) os.remove(new_name) end) + + describe("with 'autochdir'", function() + local topdir + local oldbuf + local newbuf + + before_each(function() + command('set shellslash') + topdir = fn.getcwd() + t.mkdir(topdir .. '/Xacd') + + oldbuf = api.nvim_get_current_buf() + command('vnew') + newbuf = api.nvim_get_current_buf() + command('set autochdir') + end) + + after_each(function() + t.rmdir(topdir .. '/Xacd') + end) + + it('does not change cwd with non-current buffer', function() + api.nvim_buf_set_name(oldbuf, topdir .. '/Xacd/foo.txt') + eq(topdir, fn.getcwd()) + end) + + it('changes cwd with current buffer', function() + api.nvim_buf_set_name(newbuf, topdir .. '/Xacd/foo.txt') + eq(topdir .. '/Xacd', fn.getcwd()) + end) + end) end) describe('nvim_buf_is_loaded', function() diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 2ad5f0e799..14bb0c8697 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -111,6 +111,44 @@ describe('API/win', function() api.nvim_win_set_buf(new_win, next_buf) eq(next_buf, api.nvim_win_get_buf(new_win)) end) + + describe("with 'autochdir'", function() + local topdir + local otherbuf + local oldwin + local newwin + + before_each(function() + command('set shellslash') + topdir = fn.getcwd() + t.mkdir(topdir .. '/Xacd') + t.mkdir(topdir .. '/Xacd/foo') + otherbuf = api.nvim_create_buf(false, true) + api.nvim_buf_set_name(otherbuf, topdir .. '/Xacd/baz.txt') + + command('set autochdir') + command('edit Xacd/foo/bar.txt') + eq(topdir .. '/Xacd/foo', fn.getcwd()) + + oldwin = api.nvim_get_current_win() + command('vsplit') + newwin = api.nvim_get_current_win() + end) + + after_each(function() + t.rmdir(topdir .. '/Xacd') + end) + + it('does not change cwd with non-current window', function() + api.nvim_win_set_buf(oldwin, otherbuf) + eq(topdir .. '/Xacd/foo', fn.getcwd()) + end) + + it('changes cwd with current window', function() + api.nvim_win_set_buf(newwin, otherbuf) + eq(topdir .. '/Xacd', fn.getcwd()) + end) + end) end) describe('{get,set}_cursor', function() @@ -1749,29 +1787,44 @@ describe('API/win', function() ) end) - it('do not change dir when enter is false', function() - local expected = fn.getcwd() .. '/foo' - t.mkdir('foo') - exec_lua [[ - vim.opt.autochdir = true - local buf = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_name(buf, 'Foo') - vim.api.nvim_create_autocmd('CmdlineEnter', { - callback = function() - local winid = vim.api.nvim_open_win(buf, false, { - relative = 'editor', - height = 1, - width = 1, - row = 1, - col = 1, - }) - vim.api.nvim_win_close(winid, true) - end, - }) - ]] - t.feed(':edit foo/bar.txt<CR>') - eq(t.is_os('win') and expected:gsub('/', '\\') or expected, fn.getcwd()) - t.rmdir('foo') + describe("with 'autochdir'", function() + local topdir + local otherbuf + + before_each(function() + command('set shellslash') + topdir = fn.getcwd() + t.mkdir(topdir .. '/Xacd') + t.mkdir(topdir .. '/Xacd/foo') + otherbuf = api.nvim_create_buf(false, true) + api.nvim_buf_set_name(otherbuf, topdir .. '/Xacd/baz.txt') + + command('set autochdir') + command('edit Xacd/foo/bar.txt') + eq(topdir .. '/Xacd/foo', fn.getcwd()) + end) + + after_each(function() + t.rmdir(topdir .. '/Xacd') + end) + + it('does not change cwd with enter=false #15280', function() + api.nvim_open_win( + otherbuf, + false, + { relative = 'editor', height = 5, width = 5, row = 5, col = 5 } + ) + eq(topdir .. '/Xacd/foo', fn.getcwd()) + end) + + it('changes cwd with enter=true', function() + api.nvim_open_win( + otherbuf, + true, + { relative = 'editor', height = 5, width = 5, row = 5, col = 5 } + ) + eq(topdir .. '/Xacd', fn.getcwd()) + end) end) end) |