fix(cwd): validate getcwd(…, -1)

This commit is contained in:
Justin M. Keyes
2026-08-04 15:45:45 +02:00
parent db2e86fba4
commit 46ca236525
10 changed files with 99 additions and 73 deletions

View File

@@ -1357,7 +1357,7 @@ Use |getcwd()| to get the effective directory from the current scope. The
window-local working directory takes precedence over the buffer-local working
directory, which takes precedence over the tab-local working directory, which
in turn takes precedence over the global working directory. If a local
working directory (window, buffer or tab) does not exist, the next-higher
working directory (tab, window or buffer) does not exist, the next-higher
scope in the hierarchy applies.
*:cd* *E747* *E472*
@@ -1388,7 +1388,7 @@ scope in the hierarchy applies.
*:tc* *:tcd*
:tc[d][!] {path} Like |:cd|, but only set the directory for the current
tab. The current buffer and window will also use this
tab. The current window and buffer will also use this
directory. The current directory is not changed for
windows in other tabs and for windows in the current
tab that have their own window-local directory, or for
@@ -1401,15 +1401,10 @@ scope in the hierarchy applies.
*:tch* *:tchdir*
:tch[dir][!] Same as |:tcd|.
*:bc* *:bcd*
:bc[d][!] {path} Like |:cd|, but only set the current directory for the
current buffer. The current directory for other
windows or buffers or tabs is not changed.
*:lc* *:lcd*
:lc[d][!] {path} Like |:cd|, but only set the current directory for the
current window. The current directory for other
windows, tabs, or buffers is not changed.
tabs, windows, or buffers is not changed.
*:lch* *:lchdir*
:lch[dir][!] Same as |:lcd|.
@@ -1418,6 +1413,18 @@ scope in the hierarchy applies.
:lc[d][!] - Change to the previous current directory (before the
previous ":lcd {path}" command).
*:bc* *:bcd*
:bc[d][!] [path] Like |:cd|, but only set the current directory for the
current buffer. The current directory for other
tabs, windows, or buffers is not changed.
*:bcd-*
:bc[d][!] - Change to the previous buffer-local current directory
(before the last ":bcd [path]" command).
*:bch* *:bchdir*
:bch[dir][!] Same as |:bcd|.
*:pw* *:pwd* *E187*
:pw[d] Print the current directory name.
Also see |getcwd()|.
@@ -1429,24 +1436,34 @@ scope in the hierarchy applies.
:verbose pwd
[global] /path/to/current
" Set by :lcd
:verbose pwd
[window] /path/to/current
" Set by :tcd
:verbose pwd
[tabpage] /path/to/current
So long as no |:lcd| or |:tcd| 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.
" Set by :lcd
:verbose pwd
[window] /path/to/current
" Set by :bcd
: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.
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 global or tab-local directory. When jumping to another
window the current directory is changed to the last specified local current
directory. If none was specified, the global or tab-local directory is used.
When creating a new window it inherits the local directory of the current window.
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.
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.
When changing tabs the same behaviour applies. If the current tab has no
local working directory the global working directory is used.

View File

@@ -1181,6 +1181,8 @@ Tag Command Action ~
|:ball| :ba[ll] open a window for each buffer in the buffer list
|:badd| :bad[d] add buffer to the buffer list
|:balt| :balt like ":badd" but also set the alternate file
|:bcd| :bc[d] change directory for buffer
|:bchdir| :bch[dir] change directory for buffer
|:bdelete| :bd[elete] remove a buffer from the buffer list
|:belowright| :bel[owright] make split window appear right or below
|:bfirst| :bf[irst] go to first buffer in the buffer list

View File

@@ -312,6 +312,7 @@ Command-line:
is open. The |cmdwin-char| is shown via 'statuscolumn'.
Commands:
- |:bcd|
- |:checkhealth|
- |:connect|
- |:detach|

View File

@@ -3774,9 +3774,8 @@ getcwd([{winnr} [, {tabnr} [, {bufnr}]]])
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. If {bufnr} is
-1, it is ignored, and the global working directory is
returned.
working directory of that buffer 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
@@ -5013,15 +5012,15 @@ has_key({dict}, {key}) *has_key()*
(`0|1`)
haslocaldir([{winnr} [, {tabnr} [, {bufnr} ]]]) *haslocaldir()*
Checks whether the window, tabpage or buffer has set a local
Checks whether the tabpage, window or buffer has set a local
working directory. Returns 1 when the window has set a local
path via |:lcd|, or when {winnr} is -1 and the tabpage has set
a local path via |:tcd|, or when {winnr} and {tabnr} are -1
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 or window. Missing argument
implies 0. Thus the following are equivalent: >vim
numbers, 0 means current tab, window or buffer. Missing
argument implies 0. Thus the following are equivalent: >vim
echo haslocaldir()
echo haslocaldir(0)
echo haslocaldir(0, 0)
@@ -5030,7 +5029,8 @@ haslocaldir([{winnr} [, {tabnr} [, {bufnr} ]]]) *haslocaldir()*
{winnr} is a |window-number| or |window-ID|.
If {winnr} is -1 it is ignored, only the tab is resolved.
If {bufnr} is provided, {winnr} and {tabnr} must be -1 and
only the buffer is resolved.
only the buffer is resolved. An argument may be -1 only if
all preceding arguments are -1.
Examples of buffer usage: >vim
haslocaldir(-1, -1, 0) " Current buf has a local directory?
haslocaldir(-1, -1, 3) " Buf #3 has a local directory?

View File

@@ -3341,9 +3341,8 @@ function vim.fn.getcursorcharpos(winid) end
--- 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. If {bufnr} is
--- -1, it is ignored, and the global working directory is
--- returned.
--- working directory of that buffer 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
@@ -4462,15 +4461,15 @@ function vim.fn.has(feature) end
--- @return 0|1
function vim.fn.has_key(dict, key) end
--- Checks whether the window, tabpage or buffer has set a local
--- Checks whether the tabpage, window or buffer has set a local
--- working directory. Returns 1 when the window has set a local
--- path via |:lcd|, or when {winnr} is -1 and the tabpage has set
--- a local path via |:tcd|, or when {winnr} and {tabnr} are -1
--- 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 or window. Missing argument
--- implies 0. Thus the following are equivalent: >vim
--- numbers, 0 means current tab, window or buffer. Missing
--- argument implies 0. Thus the following are equivalent: >vim
--- echo haslocaldir()
--- echo haslocaldir(0)
--- echo haslocaldir(0, 0)
@@ -4479,7 +4478,8 @@ function vim.fn.has_key(dict, key) end
--- {winnr} is a |window-number| or |window-ID|.
--- If {winnr} is -1 it is ignored, only the tab is resolved.
--- If {bufnr} is provided, {winnr} and {tabnr} must be -1 and
--- only the buffer is resolved.
--- only the buffer is resolved. An argument may be -1 only if
--- all preceding arguments are -1.
--- Examples of buffer usage: >vim
--- haslocaldir(-1, -1, 0) " Current buf has a local directory?
--- haslocaldir(-1, -1, 3) " Buf #3 has a local directory?