Problem:
:bcd (buffer-local directory) is not preserved after
`nvim_open_win` or `nvim_win_set_buf`
Analysis:
set_curbuf() ends with update_cwd(), which falls back to
os_chdir(globaldir) when the target buffer has no b_localdir.
Solution:
Pass kCtxKeepCwd to ctx_switch().
Problem:
Re-editing a buffer (`:edit!`, re-reading a dir.lua buffer, etc.) drops
its `:bcd` directory, so the CWD falls back to the global one. Whereas
other buffer-local state (`b:` vars, local options) survives a reload.
Solution:
Don't clear buf dir in `buf_freeall()`; `do_ecmd()` calls that when
reloading/re-editing. `free_buffer_stuff()` still clears them when
a buffer is freed or reused for another file.
Problem:
- buf-local CWD scope is lower priority than :lcd, which is weird.
```
win > buf > tab > global
```
- No way to clear current CWD at a given scope.
Solution:
- Rerrange scope precedence to:
```
buf > win > tab > global
```
- Introduce "bang" variants (`:bcd!`/`:lcd!`/`:tcd!`) which clears the
local CWD for the given scope.
Problem:
- Explicit `:bcd` (etc.) persists from `nvim_buf_call()` but not from an
autocmd handler targeting a hidden buf (`LspAttach`, `TermRequest`, …),
which needs a `vim.schedule()` workaround.
- `vim._with()` is supposed to work as a "sandbox", discarding
side-effects, but it leaks CWD changes: `:lcd` from a `win` context,
any chdir from a visible-buffer context.
Solution:
- Explicit :cd/:tcd/:bcd during a temp context persists by default.
- "Ambient" directory changes ('autochdir', existing win-local CWD,
etc.) are still undone, as before.
- Add `kCtxKeepDirs`: snapshot/restore the target's full CWD state
(w/b/tp-local, global, cwd). Used by `vim._with()` and `'inccommand'`,
which must not leak state.
Problem:
Buffer-local CWD (:bcd) is "sticky", similar to window-local CWD (:lcd).
But this contradicts one of its main benefits: per-buffer "project root"
for LSP, OSC7.
Other problems:
- A buffer created with :edit/:enew/:new silently inherits b_localdir
(and b_prevdir) from the previous buffer.
- curbuf_reusable() refuses to recycle a scratch buffer that has
`b_localdir`.
- After :new/:vnew/:tabnew the CWD sticks to previous buffer's
`b_localdir` even though the new curbuf has none, so :new is not
equivalent to ":split | enew", and getcwd() disagrees with
haslocaldir().
- Requires "which buffer spawned this buffer" semantics that no other
buffer-local state has.
Solution:
Drop sticky/inherit behavior of buffer-local CWD (:bcd).
- do_ecmd: always apply the new curbuf's dir (`fix_current_dir`), like
`do_autochdir` already does. :tabnew from a :bcd buffer now reverts to
global CWD (and fires DirChanged), same as :tabnew from a :lcd window.
- curbuf_reusable(): recycling a scratch buffer frees its b_localdir.
To get sticky/inherit behavior of CWD, use `:lcd`.
Problem:
No way to set a buffer-local directory.
Use-cases:
- "Root dir" for LSP (and the "project" concept).
- `:terminal` OSC 7
Solution:
Add `:bcd` command.
- Extend `getcwd()` to take a third arg; `getcwd(-1, -1, bunfr)` returns
the buffer-local working directory.
- Buffer-local directories have less priority than window-local
ones, and more priority than tab-local ones.
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
Problem:
The magic globals `it`, `describe`, etc., are more trouble than they are
worth.
- Hooking into `after_each` requires `getfenv()` hacks.
- They confuse luals/emmylua, because the top-level `.luarc.json` isn't
merged with `test/.luarc.json` (apparently a luals limitation?)
- They totally defeat discoverability because the user just has to
"know" about the various magic symbols.
So they harm DX, which means they serve no purpose at all.
Solution:
- Expose the test API from `testutil`, so tests can call `t.it()`,
`t.describe()`, etc., in the conventional way.
- Drop `getfenv()` hacks.
- Drop the `setfenv()` injection in `load_chunk`.
- Drop `test/_meta.lua`.
Specifically, functions that are run in the context of the test runner
are put in module `test/testutil.lua` while the functions that are run
in the context of the test session are put in
`test/functional/testnvim.lua`.
Closes https://github.com/neovim/neovim/issues/27004.
Extend the capabilities of is_os to detect more platforms such as
freebsd and openbsd. Also remove `iswin()` helper function as it can be
replaced by `is_os("win")`.
This is essentially a convenience wrapper around the `pending()`
function, similar to `skip_fragile()` but more general-purpose.
Also remove `pending_win32` function as it can be replaced by
`skip(iswin())`.
Problem: getcwd() is unclear about how 'autochdir' is used.
Solution: Update the help for getcwd(). Without any arguments always return
the actual current directory. (closesvim/vim#9142)
851c7a699a
Hope this will make people using feed_command less likely: this hides bugs.
Already found at least two:
1. msgpackparse() will show internal error: hash_add() in case of duplicate
keys, though it will still work correctly. Currently silenced.
2. ttimeoutlen was spelled incorrectly, resulting in option not being set when
expected. Test was still functioning somehow though. Currently fixed.
Closes#5291
Restores behaviour identical to Vim. If the user calls the VimScript
function 'getcwd()' and the working directory cannot be found (for
example because the directory has been deleted since the last time it
was used) an empty string needs to be returned instead of throwing an
error.
It is otherwise impossible to determine which test failed sanitizer/valgrind
check. test/functional/helpers.lua module return was changed so that tests which
do not provide after_each function to get new check will automatically fail.
The directories table contains the names of the expected directory names
for varying scopes of the :cd tests. Using named indexes, instead of
numbered, makes the test more readable.
Build wcwd/tcwd and wlwd/tlwd on top of the reworked cwd/lwd functions.
This will allow for easier testing of `getcwd()`/`haslocaldir()` in
arbitrary windows and/or tab pages.
While trying to debug an issue, I discovered that the tests for illegal
arguments depended on the prior suite having run and started a session.
Let's remove that unintentional dependency by starting our own session
before each test.
New ex commands: 'tcd', 'tchdir'
Changed Vimscript functions: 'haslocaldir', 'getcwd'
The ex-commands ':tcd' and ':tchdir' are the tab-local equivalents of
':lcd' and ':lchdir'. There are no new Vimscript functions introduced,
instead the functions 'haslocaldir' and 'getcwd' take in optional
arguments. See the documentation for details
Since there is now different levels of local directory a simple boolean
at source level is no longer sufficient; a new enumeration type is used
for the scope-level from now on.
The documentation has been accommodated for these new commands and
functional tests have been written to test the feature.