diff options
-rw-r--r-- | src/nvim/ex_docmd.c | 3 | ||||
-rw-r--r-- | src/nvim/file_search.c | 7 | ||||
-rw-r--r-- | src/nvim/memory.c | 7 | ||||
-rw-r--r-- | src/nvim/window.c | 36 | ||||
-rw-r--r-- | test/functional/autocmd/dirchanged_spec.lua | 28 |
5 files changed, 63 insertions, 18 deletions
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 5ab97d9b9a..745419a98f 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6962,7 +6962,6 @@ void post_chdir(CdScope scope) char curdir[MAXPATHL]; if (os_dirname((char_u *)curdir, MAXPATHL) != OK) { - EMSG2(_(e_intern2), "post_chdir()"); return; } switch (scope) { @@ -6981,7 +6980,7 @@ void post_chdir(CdScope scope) assert(false); } - shorten_fnames(TRUE); + shorten_fnames(true); do_autocmd_dirchanged(curdir, scope); } diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c index 34696ddd7f..c840c0a2d1 100644 --- a/src/nvim/file_search.c +++ b/src/nvim/file_search.c @@ -1550,10 +1550,11 @@ void do_autocmd_dirchanged(char *new_dir, CdScope scope) } dict_add_nr_str(dict, "scope", 0L, (char_u *)buf); - dict_add_nr_str(dict, "cwd", 0L, new_dir); + dict_add_nr_str(dict, "cwd", 0L, (char_u *)new_dir); dict_set_keys_readonly(dict); - apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, new_dir, false, NULL); + apply_autocmds(EVENT_DIRCHANGED, (char_u *)buf, (char_u *)new_dir, false, + NULL); dict_clear(dict); @@ -1572,7 +1573,7 @@ int vim_chdirfile(char_u *fname) if (os_chdir((char *)dir) != 0) { return FAIL; } - do_autocmd_dirchanged(dir, kCdScopeWindow); + do_autocmd_dirchanged((char *)dir, kCdScopeWindow); return OK; } diff --git a/src/nvim/memory.c b/src/nvim/memory.c index b593936d7b..58c01fbe7a 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -475,6 +475,13 @@ void *xmemdup(const void *data, size_t len) return memcpy(xmalloc(len), data, len); } +/// Returns true if strings `a` and `b` are equal. Arguments may be NULL. +bool strequal(const char *a, const char *b) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return (a == NULL && b == NULL) || (a && b && strcmp(a, b) == 0); +} + /* * Avoid repeating the error message many times (they take 1 second each). * Did_outofmem_msg is reset when a character is read. diff --git a/src/nvim/window.c b/src/nvim/window.c index 0c265a5ede..7c7d73fdfb 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -3616,28 +3616,38 @@ static void win_enter_ext(win_T *wp, bool undo_sync, int curwin_invalid, curwin->w_cursor.coladd = 0; changed_line_abv_curs(); /* assume cursor position needs updating */ - // The new directory is either the local directory of the window, tab or NULL. - char_u *new_dir = curwin->w_localdir - ? curwin->w_localdir : curtab->tp_localdir; + // New directory is either the local directory of the window, tab or NULL. + char *new_dir = (char *)(curwin->w_localdir + ? curwin->w_localdir : curtab->tp_localdir); + + char cwd[MAXPATHL]; + if (os_dirname((char_u *)cwd, MAXPATHL) != OK) { + cwd[0] = NUL; + } if (new_dir) { // Window/tab has a local directory: Save current directory as global - // directory (unless that was done already) and change to the local - // directory. + // (unless that was done already) and change to the local directory. if (globaldir == NULL) { - char_u cwd[MAXPATHL]; - - if (os_dirname(cwd, MAXPATHL) == OK) { - globaldir = vim_strsave(cwd); + if (cwd[0] != NUL) { + globaldir = (char_u *)xstrdup(cwd); } } - if (os_chdir((char *)new_dir) == 0) { + if (os_chdir(new_dir) == 0) { + if (!p_acd && !strequal(new_dir, cwd)) { + do_autocmd_dirchanged(new_dir, curwin->w_localdir + ? kCdScopeWindow : kCdScopeTab); + } shorten_fnames(true); } } else if (globaldir != NULL) { - /* Window doesn't have a local directory and we are not in the global - * directory: Change to the global directory. */ - ignored = os_chdir((char *)globaldir); + // Window doesn't have a local directory and we are not in the global + // directory: Change to the global directory. + if (os_chdir((char *)globaldir) == 0) { + if (!p_acd && !strequal((char *)globaldir, cwd)) { + do_autocmd_dirchanged((char *)globaldir, kCdScopeGlobal); + } + } xfree(globaldir); globaldir = NULL; shorten_fnames(TRUE); diff --git a/test/functional/autocmd/dirchanged_spec.lua b/test/functional/autocmd/dirchanged_spec.lua index f51a978221..7a1f79fd34 100644 --- a/test/functional/autocmd/dirchanged_spec.lua +++ b/test/functional/autocmd/dirchanged_spec.lua @@ -109,6 +109,34 @@ describe('autocmd DirChanged', function() eq({cwd=dirs[2], scope='window'}, eval('g:event')) end) + it("is triggered by switching to win/tab with different CWD #6054", function() + command('lcd '..dirs[3]) -- window 3 + command('split '..dirs[2]..'/foo') -- window 2 + command('lcd '..dirs[2]) + command('split '..dirs[1]..'/bar') -- window 1 + command('lcd '..dirs[1]) + + command('2wincmd w') -- window 2 + eq({cwd=dirs[2], scope='window'}, eval('g:event')) + + eq(4, eval('g:cdcount')) + command('tabnew') -- tab 2 (tab-local CWD) + eq(4, eval('g:cdcount')) -- same CWD, no DirChanged event + command('tcd '..dirs[3]) + command('tabnext') -- tab 1 (no tab-local CWD) + eq({cwd=dirs[2], scope='window'}, eval('g:event')) + command('tabnext') -- tab 2 + eq({cwd=dirs[3], scope='tab'}, eval('g:event')) + eq(7, eval('g:cdcount')) + + command('tabnext') -- tab 1 + command('3wincmd w') -- window 3 + eq(9, eval('g:cdcount')) + command('tabnext') -- tab 2 (has the *same* CWD) + eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event + + end) + it('is triggered by nvim_set_current_dir()', function() request('nvim_set_current_dir', dirs[1]) eq({cwd=dirs[1], scope='global'}, eval('g:event')) |