feat(cwd): support explicit chdir (:bcd/:tcd/…) in temp context

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.
This commit is contained in:
Justin M. Keyes
2026-08-05 11:20:05 +02:00
parent 93696ca903
commit 1c1dc0558f
10 changed files with 300 additions and 106 deletions

View File

@@ -1533,9 +1533,13 @@ local get_context_state = function(context)
return res
end
--- Executes function `f` with the given context specification.
--- Executes function `f` with the given `context` spec: after execution, the original state
--- indicated by the spec is restored.
---
--- Notes:
--- - If `buf`/`win` is specified, CWD state (win/buf/tab-local dirs) is restored after execution.
--- Any :cd/:tcd/:lcd/:bcd during execution is undone.
--- - TODO: allow opt-out? Workaround: use nvim_buf_call()/nvim_win_call().
--- - Context `{ buf = buf }` has no guarantees about current window when
--- inside context.
--- - Context `{ buf = buf, win = win }` is yet not allowed, but this seems