diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 02c4ce80da..98d903134d 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -615,14 +615,14 @@ DiffUpdated After diffs have been updated. Depending on *DirChanged* DirChanged After the |current-directory| was changed. The pattern can be: - "auto" to trigger on 'autochdir'. - "buffer" to trigger on `:bcd` - "global" to trigger on `:cd` - "tabpage" to trigger on `:tcd` - "window" to trigger on `:lcd` + "auto" triggered on 'autochdir'. + "buffer" triggered on `:bcd`. + "global" triggered on `:cd`. + "tabpage" triggered on `:tcd`. + "window" triggered on `:lcd`. Sets these |v:event| keys: cwd: current working directory - scope: "global", "tabpage", "window" + scope: "global", "tabpage", "window", "buffer" changed_window: v:true if we fired the event switching window (or tab) is set to the new directory name. diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index 9e09bd4121..952801d486 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -1418,6 +1418,10 @@ scope in the hierarchy applies. current buffer. The current directory for other tabs, windows, or buffers is not changed. + Unlike :lcd and :tcd, this is not "sticky": a new + buffer or window will not "inherit" a buffer-local + directory. + *:bcd-* :bc[d][!] - Change to the previous buffer-local current directory (before the last ":bcd [path]" command). @@ -1448,22 +1452,24 @@ scope in the hierarchy applies. :verbose pwd [buffer] /path/to/current -So long as no |:tcd|, |:lcd| or |:bcd| command has been used, all windows -share the same current directory. Using a command to jump to another window -doesn't change anything for the current directory. +So long as |:tcd|, |:lcd| or |:bcd| has not been used, all buffers and windows +share the same directory. Using a command to jump to another window doesn't +change anything for the current directory. When |:lcd| has been used for a window, the specified directory becomes the current directory for that window. Windows where the |:lcd| command has not been used stick to the buffer-local, tab-local or global directory. When jumping to another window the current directory is changed to the last -specified local current directory. If none was specified, the buffer-local, -tab-local or global directory is used. When creating a new window it -inherits the local directory of the current window. +specified window-local directory. If none was specified, the buffer-local, +tab-local or global directory is used. When creating a new window it inherits +the current window-local directory ("sticky" behavior). When |:bcd| has been used for a buffer, the specified directory becomes the current directory whenever that buffer is entered, unless the window has its -own window-local directory. A new buffer created with |:edit| or |:enew| -inherits the buffer-local directory of the previous current buffer. +own window-local directory. The buffer-local directory is never inherited +(not "sticky"): a buffer created with |:edit|, |:enew|, etc., ignores the +current buffer-local (:bcd) directory, if any. Use |:lcd| if you want "sticky" +behavior. When changing tabs the same behaviour applies. If the current tab has no local working directory the global working directory is used. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index c8f1d868a8..8086129f68 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1323,7 +1323,7 @@ A jump table for the options with a short description can be found at |Q_op|. 'cdhome' 'cdh' boolean (default on on Unix, off on Windows) global Disallowed in |modeline|. |no-modeline-option| - When on, |:cd|, |:tcd| and |:lcd| without an argument changes the + When on, |:cd|, |:tcd|, |:lcd| and |:bcd| without an argument changes the current working directory to the |$HOME| directory like in Unix. When off, those commands just print the current directory name. @@ -1332,7 +1332,7 @@ A jump table for the options with a short description can be found at |Q_op|. global Disallowed in |modeline|. |no-modeline-option| This is a list of directories which will be searched when using the - |:cd|, |:tcd| and |:lcd| commands, provided that the directory being + |:cd|, |:tcd|, |:lcd| and |:bcd| commands, provided that the directory being searched for has a relative path, not an absolute part starting with "/", "./" or "../", the 'cdpath' option is not used then. The 'cdpath' option's value has the same form and semantics as @@ -2058,7 +2058,7 @@ A jump table for the options with a short description can be found at |Q_op|. following occurrence. *cpo-~* ~ When included, don't resolve symbolic links when - changing directory with |:cd|, |:lcd|, or |:tcd|. + changing directory with |:cd|, |:tcd|, |:lcd|, or |:bcd|. This preserves the symbolic link path in buffer names and when displaying the current directory. When excluded (default), symbolic links are resolved to diff --git a/runtime/doc/vimfn.txt b/runtime/doc/vimfn.txt index 38be4b38f3..806ee13d2e 100644 --- a/runtime/doc/vimfn.txt +++ b/runtime/doc/vimfn.txt @@ -1125,8 +1125,8 @@ chdir({dir} [, {scope}]) *chdir()* If {scope} is present, changes the current working directory for the specified scope: - "window" Changes the window local directory. |:lcd| "buffer" Changes the buffer local directory. |:bcd| + "window" Changes the window local directory. |:lcd| "tabpage" Changes the tabpage local directory. |:tcd| "global" Changes the global directory. |:cd| @@ -3759,23 +3759,27 @@ getcwd([{winnr} [, {tabnr} [, {bufnr}]]]) is ignored. Tabs, windows and buffers are identified by their respective - numbers, 0 means current tab or window or buffer. Missing tab - number - implies 0. Thus the following are equivalent: >vim + numbers, 0 means current tab/window/buffer. Missing {tabnr} + implies 0 (missing {bufnr} does not; see below). Thus the + following are equivalent: >vim getcwd(0) getcwd(0, 0) < If {winnr} is -1 it is ignored, only the tab is resolved. {winnr} is a |window-number| or |window-ID|. + If both {winnr} and {tabnr} are -1 and {bufnr} is missing the global working directory is returned. + Note: When {tabnr} is -1 Vim returns an empty string to signal that it is invalid, whereas Nvim returns either the global working directory if {winnr} is -1 or the working directory of the window indicated by {winnr}. - If {bufnr} is provided, {winnr} and {tabnr} must be -1 and the - working directory of that buffer is returned. An argument may - be -1 only if all preceding arguments are -1. + If {bufnr} is provided, {winnr} and {tabnr} must be -1, then + the buffer-local working directory is returned. + + An argument may be -1 only if all preceding arguments are -1. + Examples of buffer usage: >vim getcwd(-1, -1, 0) " Get current buffer's directory getcwd(-1, -1, 3) " Get directory of buffer #3 @@ -5019,8 +5023,9 @@ haslocaldir([{winnr} [, {tabnr} [, {bufnr} ]]]) *haslocaldir()* and {bufnr} has set a local path via |:bcd|, otherwise 0. Tabs, windows and buffers are identified by their respective - numbers, 0 means current tab, window or buffer. Missing - argument implies 0. Thus the following are equivalent: >vim + numbers, 0 means current tab/window/buffer. Missing {winnr} + or {tabnr} implies 0 (missing {bufnr} does not; see below). + Thus the following are equivalent: >vim echo haslocaldir() echo haslocaldir(0) echo haslocaldir(0, 0) diff --git a/runtime/lua/vim/_meta/options.gen.lua b/runtime/lua/vim/_meta/options.gen.lua index dd2d1a7468..6932bbfca5 100644 --- a/runtime/lua/vim/_meta/options.gen.lua +++ b/runtime/lua/vim/_meta/options.gen.lua @@ -734,7 +734,7 @@ vim.o.cmp = vim.o.casemap vim.go.casemap = vim.o.casemap vim.go.cmp = vim.go.casemap ---- When on, `:cd`, `:tcd` and `:lcd` without an argument changes the +--- When on, `:cd`, `:tcd`, `:lcd` and `:bcd` without an argument changes the --- current working directory to the `$HOME` directory like in Unix. --- When off, those commands just print the current directory name. --- @@ -745,7 +745,7 @@ vim.go.cdhome = vim.o.cdhome vim.go.cdh = vim.go.cdhome --- This is a list of directories which will be searched when using the ---- `:cd`, `:tcd` and `:lcd` commands, provided that the directory being +--- `:cd`, `:tcd`, `:lcd` and `:bcd` commands, provided that the directory being --- searched for has a relative path, not an absolute part starting with --- "/", "./" or "../", the 'cdpath' option is not used then. --- The 'cdpath' option's value has the same form and semantics as @@ -1572,7 +1572,7 @@ vim.bo.ci = vim.bo.copyindent --- following occurrence. --- *cpo-~* --- ~ When included, don't resolve symbolic links when ---- changing directory with `:cd`, `:lcd`, or `:tcd`. +--- changing directory with `:cd`, `:tcd`, `:lcd`, or `:bcd`. --- This preserves the symbolic link path in buffer names --- and when displaying the current directory. When --- excluded (default), symbolic links are resolved to diff --git a/runtime/lua/vim/_meta/vimfn.gen.lua b/runtime/lua/vim/_meta/vimfn.gen.lua index 1806838eb4..8444b6d6f4 100644 --- a/runtime/lua/vim/_meta/vimfn.gen.lua +++ b/runtime/lua/vim/_meta/vimfn.gen.lua @@ -960,8 +960,8 @@ function vim.fn.charidx(string, idx, countcc, utf16) end --- --- If {scope} is present, changes the current working directory --- for the specified scope: ---- "window" Changes the window local directory. |:lcd| --- "buffer" Changes the buffer local directory. |:bcd| +--- "window" Changes the window local directory. |:lcd| --- "tabpage" Changes the tabpage local directory. |:tcd| --- "global" Changes the global directory. |:cd| --- @@ -3326,23 +3326,27 @@ function vim.fn.getcursorcharpos(winid) end --- is ignored. --- --- Tabs, windows and buffers are identified by their respective ---- numbers, 0 means current tab or window or buffer. Missing tab ---- number ---- implies 0. Thus the following are equivalent: >vim +--- numbers, 0 means current tab/window/buffer. Missing {tabnr} +--- implies 0 (missing {bufnr} does not; see below). Thus the +--- following are equivalent: >vim --- getcwd(0) --- getcwd(0, 0) --- vim --- getcwd(-1, -1, 0) " Get current buffer's directory --- getcwd(-1, -1, 3) " Get directory of buffer #3 @@ -4468,8 +4472,9 @@ function vim.fn.has_key(dict, key) end --- and {bufnr} has set a local path via |:bcd|, otherwise 0. --- --- Tabs, windows and buffers are identified by their respective ---- numbers, 0 means current tab, window or buffer. Missing ---- argument implies 0. Thus the following are equivalent: >vim +--- numbers, 0 means current tab/window/buffer. Missing {winnr} +--- or {tabnr} implies 0 (missing {bufnr} does not; see below). +--- Thus the following are equivalent: >vim --- echo haslocaldir() --- echo haslocaldir(0) --- echo haslocaldir(0, 0) diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 62f332740f..db94778e36 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1778,7 +1778,7 @@ void set_curbuf(buf_T *buf, int action, bool update_jumplist) } // Maybe cd to buffer-local directory - fix_current_dir(false); + update_cwd(kCdCauseBuffer); } /// Enter a new current buffer. @@ -2031,8 +2031,6 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags) trigger_undo_ftplugin(buf, curwin); // It's like this buffer is deleted. Watch out for autocommands that // change curbuf! If that happens, allocate a new buffer anyway. - // We also ask it to not free the buffer-local directory so we can reuse - // it. buf_freeall(buf, BFA_WIPE | BFA_DEL); if (aborting()) { // autocmds may abort script processing xfree(ffname); @@ -2162,8 +2160,6 @@ bool curbuf_reusable(void) && curbuf->b_ffname == NULL && curbuf->b_nwindows <= 1 && !curbuf->terminal - && curbuf->b_localdir == NULL - && curbuf->b_prevdir == NULL && (curbuf->b_ml.ml_mfp == NULL || buf_is_empty(curbuf)) && !bt_quickfix(curbuf) && !curbufIsChanged()); diff --git a/src/nvim/context.c b/src/nvim/context.c index 769b4b31f5..911f2dd116 100644 --- a/src/nvim/context.c +++ b/src/nvim/context.c @@ -583,7 +583,7 @@ void ctx_restore(CtxSwitch *cs) // If :lcd has been used in the autocommand window, correct current // directory before restoring b_localdir, tp_localdir and globaldir. if (cwp->w_localdir != NULL) { - fix_current_dir(true); + update_cwd(kCdCauseWindow); } if (bufref_valid(&cs->cs_new_curbuf)) { xfree(cs->cs_new_curbuf.br_buf->b_localdir); diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 4df067481e..3181857b53 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -1265,8 +1265,8 @@ M.funcs = { If {scope} is present, changes the current working directory for the specified scope: - "window" Changes the window local directory. |:lcd| "buffer" Changes the buffer local directory. |:bcd| + "window" Changes the window local directory. |:lcd| "tabpage" Changes the tabpage local directory. |:tcd| "global" Changes the global directory. |:cd| @@ -4101,23 +4101,27 @@ M.funcs = { is ignored. Tabs, windows and buffers are identified by their respective - numbers, 0 means current tab or window or buffer. Missing tab - number - implies 0. Thus the following are equivalent: >vim + numbers, 0 means current tab/window/buffer. Missing {tabnr} + implies 0 (missing {bufnr} does not; see below). Thus the + following are equivalent: >vim getcwd(0) getcwd(0, 0) vim getcwd(-1, -1, 0) " Get current buffer's directory getcwd(-1, -1, 3) " Get directory of buffer #3 @@ -5435,8 +5439,9 @@ M.funcs = { and {bufnr} has set a local path via |:bcd|, otherwise 0. Tabs, windows and buffers are identified by their respective - numbers, 0 means current tab, window or buffer. Missing - argument implies 0. Thus the following are equivalent: >vim + numbers, 0 means current tab/window/buffer. Missing {winnr} + or {tabnr} implies 0 (missing {bufnr} does not; see below). + Thus the following are equivalent: >vim echo haslocaldir() echo haslocaldir(0) echo haslocaldir(0, 0) diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index e5584a5353..782dd9b9d8 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2937,23 +2937,8 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum redraw_curbuf_later(UPD_NOT_VALID); // redraw this buffer later } - // A new buffer inherits the buffer-local directory of the buffer it was created from (unless - // autocommands already set one). - if (!oldbuf && curbuf->b_localdir == NULL - && bufref_valid(&old_curbuf) - && old_curbuf.br_buf != curbuf - && old_curbuf.br_buf->b_localdir != NULL) { - curbuf->b_localdir = xstrdup(old_curbuf.br_buf->b_localdir); - if (old_curbuf.br_buf->b_prevdir != NULL) { - curbuf->b_prevdir = xstrdup(old_curbuf.br_buf->b_prevdir); - } - } - - // If editing a buffer in the current window, make sure to update to the - // buffer's working directory. - if (oldwin == curwin) { - fix_current_dir(false); - } + // Update to the working directory of the new current buffer. + update_cwd(kCdCauseBuffer); // Change directories when the 'acd' option is set. do_autochdir(); diff --git a/src/nvim/options.lua b/src/nvim/options.lua index bf487a6d59..a070861233 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1093,7 +1093,7 @@ local options = { doc = [[on on Unix, off on Windows]], }, desc = [=[ - When on, |:cd|, |:tcd| and |:lcd| without an argument changes the + When on, |:cd|, |:tcd|, |:lcd| and |:bcd| without an argument changes the current working directory to the |$HOME| directory like in Unix. When off, those commands just print the current directory name. ]=], @@ -1113,7 +1113,7 @@ local options = { deny_duplicates = true, desc = [=[ This is a list of directories which will be searched when using the - |:cd|, |:tcd| and |:lcd| commands, provided that the directory being + |:cd|, |:tcd|, |:lcd| and |:bcd| commands, provided that the directory being searched for has a relative path, not an absolute part starting with "/", "./" or "../", the 'cdpath' option is not used then. The 'cdpath' option's value has the same form and semantics as @@ -2119,7 +2119,7 @@ local options = { following occurrence. *cpo-~* ~ When included, don't resolve symbolic links when - changing directory with |:cd|, |:lcd|, or |:tcd|. + changing directory with |:cd|, |:tcd|, |:lcd|, or |:bcd|. This preserves the symbolic link path in buffer names and when displaying the current directory. When excluded (default), symbolic links are resolved to diff --git a/src/nvim/window.c b/src/nvim/window.c index a4cdf68784..d880fc2f8d 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -5300,7 +5300,7 @@ static void win_enter_ext(win_T *const wp, const int flags) win_fix_cursor(get_real_state() & (MODE_NORMAL|MODE_CMDLINE|MODE_TERMINAL)); } - fix_current_dir(true); + update_cwd(kCdCauseWindow); entering_window(curwin); // Careful: autocommands may close the window and make "wp" invalid @@ -5352,11 +5352,12 @@ static void win_enter_ext(win_T *const wp, const int flags) do_autochdir(); } -/// Used after making another window or buffer the current one: change directory if needed. -void fix_current_dir(bool caused_by_win) +/// Applies the effective current-directory of the current window (its window-local, buffer-local, +/// tab-local or the global directory). Called after setting curbuf/curwin. +/// +/// @param cause What caused the switch, reported by the DirChanged event. +void update_cwd(CdCause cause) { - CdCause cause = caused_by_win ? kCdCauseWindow : kCdCauseBuffer; - // New directory is either the local directory of the window, buffer, tab or NULL. char *new_dir; CdScope scope; diff --git a/test/functional/autocmd/dirchanged_spec.lua b/test/functional/autocmd/dirchanged_spec.lua index b743069ed2..6a7f7b9a6c 100644 --- a/test/functional/autocmd/dirchanged_spec.lua +++ b/test/functional/autocmd/dirchanged_spec.lua @@ -6,7 +6,6 @@ local describe, it, before_each, setup, teardown = local clear = n.clear local command = n.command local eq = t.eq -local pcall_err = t.pcall_err local eval = n.eval local request = n.request local is_os = t.is_os @@ -162,7 +161,7 @@ describe('autocmd DirChanged and DirChangedPre', function() eq('E344:', string.match(err3, 'E%d*:')) end) - it("are triggered by 'autochdir'", function() + it("triggered by 'autochdir'", function() command('set autochdir') command('split ' .. dirs[1] .. '/foo') @@ -181,7 +180,7 @@ describe('autocmd DirChanged and DirChangedPre', function() eq(2, eval('g:cdcount')) end) - it('do not trigger if directory has not changed', function() + it('not triggered if directory has not changed', function() command('lcd ' .. dirs[1]) eq({ directory = dirs[1], scope = 'window', changed_window = false }, eval('g:evpre')) eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev')) @@ -299,7 +298,7 @@ describe('autocmd DirChanged and DirChangedPre', function() end end) - it('are triggered by switching to win/tab with different CWD #6054', function() + it('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]) @@ -376,7 +375,7 @@ describe('autocmd DirChanged and DirChangedPre', function() end end) - it('are triggered by switching to buf/tab with different CWD', function() + it('triggered by switching to buf/tab with different CWD', function() local files = { dirs[1] .. '/file', dirs[2] .. '/file', @@ -400,9 +399,10 @@ describe('autocmd DirChanged and DirChangedPre', function() eq(5, eval('g:cdprecount')) eq(5, eval('g:cdcount')) - command('tabnew') -- tab 2 (tab-local CWD) - eq(5, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(5, eval('g:cdcount')) -- same CWD, no DirChanged event + command('tabnew') -- tab 2: its new empty buffer has no local CWD, reverts to global + eq({ cwd = curdir, scope = 'global', changed_window = false }, eval('g:ev')) + eq(6, eval('g:cdprecount')) + eq(6, eval('g:cdcount')) command('tcd ' .. dirs[2]) command('tabnext') -- tab 1 (no tab-local CWD) eq({ directory = dirs[3], scope = 'buffer', changed_window = true }, eval('g:evpre')) @@ -414,55 +414,55 @@ describe('autocmd DirChanged and DirChangedPre', function() eq({ cwd = dirs[2], scope = 'tabpage', changed_window = true }, eval('g:ev')) eq('tabpage', eval('g:amatchpre')) eq('tabpage', eval('g:amatch')) - eq(8, eval('g:cdprecount')) - eq(8, eval('g:cdcount')) + eq(9, eval('g:cdprecount')) + eq(9, eval('g:cdcount')) command('tabnext') -- tab 1 command('b ' .. files[2]) -- buffer 2 - eq(10, eval('g:cdprecount')) - eq(10, eval('g:cdcount')) + eq(11, eval('g:cdprecount')) + eq(11, eval('g:cdcount')) command('tabnext') -- tab 2 (has the *same* CWD) - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event if is_os('win') then command('tabnew') -- tab 3 - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event command('tcd ' .. dirs[2]) - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabnext') -- tab 1 - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabprevious') -- tab 3 - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabprevious') -- tab 2 - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabprevious') -- tab 1 - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event command('bcd ' .. dirs[2]) -- buffer 2 - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabnext') -- tab 2 - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabnext') -- tab 3 - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabnext') -- tab 1 - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event command('tabprevious') -- tab 3 - eq(10, eval('g:cdprecount')) -- same CWD, no DirChangedPre event - eq(10, eval('g:cdcount')) -- same CWD, no DirChanged event + eq(11, eval('g:cdprecount')) -- same CWD, no DirChangedPre event + eq(11, eval('g:cdcount')) -- same CWD, no DirChanged event end end) - it('are triggered by switching to buf/win with different CWD', function() + it('triggered by switching to buf/win with different CWD', function() command('lcd ' .. dirs[3]) -- window 3 command(('split %s/file'):format(dirs[2])) -- window 2 command('lcd ' .. dirs[2]) @@ -511,7 +511,7 @@ describe('autocmd DirChanged and DirChangedPre', function() eq(8, eval('g:cdcount')) -- no DirChanged event, window-local CWD has higher priority end) - it('are triggered by nvim_set_current_dir()', function() + it('triggered by nvim_set_current_dir()', function() request('nvim_set_current_dir', dirs[1]) eq({ directory = dirs[1], scope = 'global', changed_window = false }, eval('g:evpre')) eq({ cwd = dirs[1], scope = 'global', changed_window = false }, eval('g:ev')) diff --git a/test/functional/ex_cmds/cd_spec.lua b/test/functional/ex_cmds/cd_spec.lua index 6385b6f93f..6c8ff1ceb4 100644 --- a/test/functional/ex_cmds/cd_spec.lua +++ b/test/functional/ex_cmds/cd_spec.lua @@ -179,13 +179,9 @@ for _, cmd in ipairs { 'cd', 'chdir' } do eq(globalDir, cwd()) eq(0, blwd()) - -- A new buffer created with :edit inherits the buffer-local directory; editing an - -- existing buffer keeps that buffer's own directory. + -- A new buffer created with :edit does not inherit the buffer-local directory. command('b# ') command(('e %s3'):format(tmpfile)) - eq(1, blwd()) - eq(join(globalDir, directories.buffer), cwd()) - command(('e ..%s%s1'):format(pathsep, tmpfile)) eq(0, blwd()) eq(globalDir, cwd()) @@ -406,26 +402,32 @@ for _, cmd in ipairs { 'bcd', 'bchdir' } do command('bd') -- delete buffer end) - it('makes :new/:vnew/:enew use the buffer-local directory', function() + it('buffer-local directory is NOT sticky/inherited', function() local bufdir = join(directories.start, directories.buffer) + + command('edit ' .. tmpfile) command(('%s %s'):format(cmd, directories.buffer)) - - command(':new') - eq(bufdir, cwd()) - command('wincmd x') -- close :new window - - command(':vnew') - eq(bufdir, cwd()) - command('wincmd x') -- close :vnew window - - command(':enew') eq(bufdir, cwd()) - -- Also in a split. - command(':vsplit') + -- A new buffer starts without a buffer-local directory. + command('new') + eq(directories.start, cwd()) + eq(0, blwd()) + command('close') eq(bufdir, cwd()) - command(':enew') + command('enew') + eq(directories.start, cwd()) + eq(0, blwd()) + command('b# ') eq(bufdir, cwd()) + + -- Recycling an empty unnamed buffer (:edit) drops its directory with it. + command('enew') + command(('%s %s'):format(cmd, directories.buffer)) + eq(bufdir, cwd()) + command('edit ' .. tmpfile .. '2') + eq(directories.start, cwd()) + eq(0, blwd()) end) end) end