vim-patch:9.1.1605: cannot specify scope for chdir() (#35239)

Problem:  Cannot specify scope for chdir()
Solution: Add optional scope argument (kuuote)

closes: vim/vim#17888

8a65a49d50

Co-authored-by: kuuote <znmxodq1@gmail.com>
This commit is contained in:
zeertzjq
2025-08-08 21:50:41 +08:00
committed by GitHub
parent 36361d6e4a
commit 798cb0f19a
6 changed files with 79 additions and 33 deletions

View File

@@ -302,6 +302,7 @@ UI
VIMSCRIPT
• |chdir()| allows optionally specifying a scope argument.
• |cmdcomplete_info()| gets current cmdline completion info.
• |getcompletiontype()| gets command-line completion type for any string.
• |prompt_getinput()| gets current user-input in prompt-buffer.

View File

@@ -1008,16 +1008,23 @@ charidx({string}, {idx} [, {countcc} [, {utf16}]]) *charidx()*
Return: ~
(`integer`)
chdir({dir}) *chdir()*
Change the current working directory to {dir}. The scope of
the directory change depends on the directory of the current
window:
- If the current window has a window-local directory
(|:lcd|), then changes the window local directory.
- Otherwise, if the current tabpage has a local
directory (|:tcd|) then changes the tabpage local
directory.
- Otherwise, changes the global directory.
chdir({dir} [, {scope}]) *chdir()*
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.
- Otherwise, if the tab page local directory (|:tcd|) is
set, it changes the current directory for that scope.
- Otherwise, changes the global directory for that scope.
If {scope} is present, changes the current working directory
for the specified scope:
"window" Changes the window local directory. |:lcd|
"tabpage" Changes the tab page 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.
@@ -1033,6 +1040,7 @@ chdir({dir}) *chdir()*
Parameters: ~
• {dir} (`string`)
• {scope} (`string?`)
Return: ~
(`string`)

View File

@@ -873,15 +873,22 @@ function vim.fn.charcol(expr, winid) end
--- @return integer
function vim.fn.charidx(string, idx, countcc, utf16) end
--- Change the current working directory to {dir}. The scope of
--- the directory change depends on the directory of the current
--- window:
--- - If the current window has a window-local directory
--- (|:lcd|), then changes the window local directory.
--- - Otherwise, if the current tabpage has a local
--- directory (|:tcd|) then changes the tabpage local
--- directory.
--- - Otherwise, changes the global directory.
--- 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.
--- - Otherwise, if the tab page local directory (|:tcd|) is
--- set, it changes the current directory for that scope.
--- - Otherwise, changes the global directory for that scope.
---
--- If {scope} is present, changes the current working directory
--- for the specified scope:
--- "window" Changes the window local directory. |:lcd|
--- "tabpage" Changes the tab page 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.
@@ -896,8 +903,9 @@ function vim.fn.charidx(string, idx, countcc, utf16) end
--- <
---
--- @param dir string
--- @param scope? string
--- @return string
function vim.fn.chdir(dir) end
function vim.fn.chdir(dir, scope) end
--- Get the amount of indent for line {lnum} according the
--- |C-indenting| rules, as with 'cindent'.

View File

@@ -1190,18 +1190,25 @@ M.funcs = {
signature = 'charidx({string}, {idx} [, {countcc} [, {utf16}]])',
},
chdir = {
args = 1,
args = { 1, 2 },
base = 1,
desc = [=[
Change the current working directory to {dir}. The scope of
the directory change depends on the directory of the current
window:
- If the current window has a window-local directory
(|:lcd|), then changes the window local directory.
- Otherwise, if the current tabpage has a local
directory (|:tcd|) then changes the tabpage local
directory.
- Otherwise, changes the global directory.
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.
- Otherwise, if the tab page local directory (|:tcd|) is
set, it changes the current directory for that scope.
- Otherwise, changes the global directory for that scope.
If {scope} is present, changes the current working directory
for the specified scope:
"window" Changes the window local directory. |:lcd|
"tabpage" Changes the tab page 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.
@@ -1217,9 +1224,9 @@ M.funcs = {
]=],
name = 'chdir',
params = { { 'dir', 'string' } },
params = { { 'dir', 'string' }, { 'scope', 'string' } },
returns = 'string',
signature = 'chdir({dir})',
signature = 'chdir({dir} [, {scope}])',
},
cindent = {
args = 1,

View File

@@ -74,7 +74,19 @@ void f_chdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
xfree(cwd);
CdScope scope = kCdScopeGlobal;
if (curwin->w_localdir != NULL) {
if (argvars[1].v_type != VAR_UNKNOWN) {
const char *s = tv_get_string(&argvars[1]);
if (strcmp(s, "global") == 0) {
scope = kCdScopeGlobal;
} else if (strcmp(s, "tabpage") == 0) {
scope = kCdScopeTabpage;
} else if (strcmp(s, "window") == 0) {
scope = kCdScopeWindow;
} else {
semsg(_(e_invargNval), "scope", s);
return;
}
} else if (curwin->w_localdir != NULL) {
scope = kCdScopeWindow;
} else if (curtab->tp_localdir != NULL) {
scope = kCdScopeTabpage;

View File

@@ -99,10 +99,20 @@ func Test_chdir_func()
call assert_equal('y', fnamemodify(getcwd(3, 2), ':t'))
call assert_equal('testdir', fnamemodify(getcwd(1, 1), ':t'))
" Forcing scope
call chdir('.', 'global')
call assert_match('^\[global\]', trim(execute('verbose pwd')))
call chdir('.', 'tabpage')
call assert_match('^\[tabpage\]', trim(execute('verbose pwd')))
call chdir('.', 'window')
call assert_match('^\[window\]', trim(execute('verbose pwd')))
" Error case
call assert_fails("call chdir('dir-abcd')", 'E344:')
silent! let d = chdir("dir_abcd")
call assert_equal("", d)
call assert_fails("call chdir('.', v:_null_string)", 'E475:')
call assert_fails("call chdir('.', [])", 'E730:')
" Should not crash
call chdir(d)
call assert_equal('', chdir([]))