feat(cwd)!: :lcd! (bang), rearrange :bcd/:lcd/… scope precedence #41194

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.
This commit is contained in:
Justin M. Keyes
2026-08-07 04:41:37 -04:00
committed by GitHub
parent 0e8903f44b
commit a4a544032a
15 changed files with 452 additions and 383 deletions

View File

@@ -947,30 +947,22 @@ function vim.fn.charcol(expr, winid) end
--- @return integer
function vim.fn.charidx(string, idx, countcc, utf16) end
--- Lua: Prefer |nvim_set_current_dir()| for the global directory; tab-local, window-local, and return semantics differ.
--- Sets the |current-directory| of the given {scope}:
--- - "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|
---
--- Changes the current working directory to {dir}. The scope of
--- the change is determined as follows:
--- If {scope} is not present, the current working directory is
--- changed to the scope of the current directory:
--- - If the window local directory (|:lcd|) is set, it
--- changes the current working directory for that scope.
--- - If the buffer local directory (|:bcd|) is set, it
--- changes the current working directory for that scope.
--- - Otherwise, if the tabpage local directory (|:tcd|) is
--- set, it changes the current directory for that scope.
--- - Otherwise, changes the global directory for that scope.
--- If {scope} is not given it is decided as follows:
--- - If buffer-local directory (|:bcd|) is set, scope is
--- "buffer".
--- - If the window-local directory (|:lcd|) is set, scope is
--- "window".
--- - If the tabpage-local directory (|:tcd|) is set, scope is
--- "tabpage".
--- - Otherwise, scope is "global".
---
--- If {scope} is present, changes the current working directory
--- for the specified scope:
--- "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|
---
--- {dir} must be a String.
--- If successful, returns the previous working directory. Pass
--- this to another chdir() to restore the directory.
--- If successful, returns the previous working directory.
--- On failure, returns an empty string.
---
--- Example: >vim
@@ -3321,41 +3313,37 @@ function vim.fn.getcurpos(winid) end
--- @return any
function vim.fn.getcursorcharpos(winid) end
--- Lua: Prefer |uv.cwd()| for the global working directory; tab-local and window-local scopes differ.
--- Without arguments, returns the effective |current-directory|.
--- With {winnr} (|window-number| or |window-ID|), {tabnr} or
--- {bufnr} the working directory of that scope is returned,
--- ignoring 'autochdir'.
---
--- With no arguments, returns the name of the effective
--- |current-directory|. With {winnr} or {tabnr} or {bufnr} the
--- working directory of that scope is returned, and 'autochdir'
--- is ignored.
--- - If {winnr} is -1: gets the tabpage directory.
--- - If {winnr} and {tabnr} are both -1: gets the global
--- directory.
--- - Note: Vim returns an empty string when {tabnr} is -1.
--- - If {bufnr} is given: gets the buffer-local directory.
--- ({winnr} and {tabnr} must be -1.)
--- - An argument may be -1 only if preceding args are -1. *E5001*
---
--- Tabs, windows and buffers are identified by their respective
--- 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|.
--- getcwd(0)
--- getcwd(0, 0)
--- <
--- Each form reports its own scope or "wider", so e.g. {winnr}
--- never reports a buffer-local directory. The {bufnr} form
--- falls back to the global directory, because a buffer belongs
--- to no particular window or tabpage.
---
--- 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, 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
--- Examples: >vim
--- getcwd(-1, -1, 0) " Get current buffer's directory
--- getcwd(-1, -1, 3) " Get directory of buffer #3
--- getcwd(-1, -1, 3) " Get directory of buffer 3
--- getcwd(-1, -1, -1) " Get global directory
--- getcwd(-1, -1) " Get global directory
--- <Throw error if the arguments are invalid.
--- <
---
--- @param winnr? integer
--- @param tabnr? integer