diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 218920965c..1d56e593b4 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -509,6 +509,7 @@ bool win_execute_before(win_execute_T *args, win_T *wp, tabpage_T *tp) args->curpos = wp->w_cursor; args->cwd_status = FAIL; args->apply_acd = false; + args->save_sfname = NULL; // Getting and setting directory can be slow on some systems, only do // this when the current or target window/tab have a local directory or @@ -523,6 +524,9 @@ bool win_execute_before(win_execute_T *args, win_T *wp, tabpage_T *tp) // If 'acd' is set, check we are using that directory. If yes, then // apply 'acd' afterwards, otherwise restore the current directory. if (args->cwd_status == OK && p_acd) { + if (curbuf->b_sfname != NULL && curbuf->b_fname == curbuf->b_sfname) { + args->save_sfname = xstrdup(curbuf->b_sfname); + } do_autochdir(); char autocwd[MAXPATHL]; if (os_dirname(autocwd, MAXPATHL) == OK) { @@ -543,9 +547,15 @@ void win_execute_after(win_execute_T *args) restore_win_noblock(&args->switchwin, true); if (args->apply_acd) { + xfree(args->save_sfname); do_autochdir(); } else if (args->cwd_status == OK) { os_chdir(args->cwd); + if (args->save_sfname != NULL) { + xfree(curbuf->b_sfname); + curbuf->b_sfname = args->save_sfname; + curbuf->b_fname = curbuf->b_sfname; + } } // Update the status line if the cursor moved. diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h index 07a1327526..888c7a596a 100644 --- a/src/nvim/eval/window.h +++ b/src/nvim/eval/window.h @@ -23,6 +23,7 @@ typedef struct { char cwd[MAXPATHL]; int cwd_status; bool apply_acd; + char *save_sfname; switchwin_T switchwin; } win_execute_T; diff --git a/test/functional/legacy/autochdir_spec.lua b/test/functional/legacy/autochdir_spec.lua index 3bfa8bcd1e..7e8f109334 100644 --- a/test/functional/legacy/autochdir_spec.lua +++ b/test/functional/legacy/autochdir_spec.lua @@ -32,6 +32,7 @@ describe('autochdir behavior', function() eq(dir, eval([[substitute(getcwd(), '.*/\(\k*\)', '\1', '')]])) end) + -- oldtest: Test_set_filename_other_window() it(':file in win_execute() does not cause wrong directory', function() command('cd ' .. dir) source([[ @@ -64,6 +65,7 @@ describe('autochdir behavior', function() expected_empty() end) + -- oldtest: Test_acd_win_execute() it('win_execute() does not change directory', function() local subdir = 'Xfile' command('cd ' .. dir) @@ -78,6 +80,7 @@ describe('autochdir behavior', function() matches(dir .. '$', eval('getcwd()')) end) + -- oldtest: Test_verbose_pwd() it(':verbose pwd shows whether autochdir is used', function() local subdir = 'Xautodir' command('cd ' .. dir) @@ -115,4 +118,28 @@ describe('autochdir behavior', function() command('wincmd w') matches('%[window%].*' .. dir .. '/' .. subdir .. '$', exec_capture('verbose pwd')) end) + + it('overriding via :lcd is not clobbered by win_execute()', function() + command('cd ' .. dir) + source([[ + func Test_lcd_win_execute() + let startdir = getcwd() + call mkdir('Xsubdir', 'R') + set autochdir + edit Xsubdir/file + call assert_match('_autochdir.Xsubdir.file$', expand('%:p')) + split + lcd .. + call assert_match('_autochdir.Xsubdir.file$', expand('%:p')) + call win_execute(win_getid(2), "") + call assert_match('_autochdir.Xsubdir.file$', expand('%:p')) + + set noautochdir + bwipe! + call chdir(startdir) + endfunc + ]]) + call('Test_lcd_win_execute') + expected_empty() + end) end) diff --git a/test/old/testdir/test_cd.vim b/test/old/testdir/test_cd.vim index 0c5ce294b3..03f114cf41 100644 --- a/test/old/testdir/test_cd.vim +++ b/test/old/testdir/test_cd.vim @@ -192,6 +192,28 @@ func Test_lcd_split() quit! endfunc +" Test that a temporary override of 'autochdir' via :lcd isn't clobbered by win_execute() in a split window. +func Test_lcd_win_execute() + CheckFunction test_autochdir + CheckOption autochdir + + let startdir = getcwd() + call mkdir('Xsubdir', 'R') + call test_autochdir() + set autochdir + edit Xsubdir/file + call assert_match('testdir.Xsubdir.file$', expand('%:p')) + split + lcd .. + call assert_match('testdir.Xsubdir.file$', expand('%:p')) + call win_execute(win_getid(2), "") + call assert_match('testdir.Xsubdir.file$', expand('%:p')) + + set noautochdir + bwipe! + call chdir(startdir) +endfunc + func Test_cd_from_non_existing_dir() CheckNotMSWindows