aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/eval.txt6
-rw-r--r--src/nvim/buffer.c2
-rw-r--r--src/nvim/eval/funcs.c14
-rw-r--r--src/nvim/ex_docmd.c5
-rw-r--r--src/nvim/globals.h2
-rw-r--r--src/nvim/path.c16
-rw-r--r--src/nvim/testdir/test_autochdir.vim38
-rw-r--r--src/nvim/testdir/test_cd.vim39
-rw-r--r--src/nvim/window.c2
-rw-r--r--test/functional/ex_cmds/cd_spec.lua13
-rw-r--r--test/functional/legacy/autochdir_spec.lua38
-rw-r--r--test/functional/legacy/fnamemodify_spec.lua2
-rw-r--r--test/functional/lua/uri_spec.lua6
-rw-r--r--test/unit/path_spec.lua14
14 files changed, 165 insertions, 32 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index eb3dbd9b70..da39a56164 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -5001,11 +5001,11 @@ getcurpos() Get the position of the cursor. This is like getpos('.'), but
getcwd([{winnr}[, {tabnr}]]) *getcwd()*
With no arguments, returns the name of the effective
|current-directory|. With {winnr} or {tabnr} the working
- directory of that scope is returned.
+ directory of that scope is returned, and 'autochdir' is
+ ignored.
Tabs and windows are identified by their respective numbers,
- 0 means current tab or window. Missing argument implies 0.
+ 0 means current tab or window. Missing tab number implies 0.
Thus the following are equivalent: >
- getcwd()
getcwd(0)
getcwd(0, 0)
< If {winnr} is -1 it is ignored, only the tab is resolved.
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 1512d6bcd5..f2f4950e58 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -1587,7 +1587,7 @@ void do_autochdir(void)
if (starting == 0
&& curbuf->b_ffname != NULL
&& vim_chdirfile(curbuf->b_ffname, kCdCauseAuto) == OK) {
- post_chdir(kCdScopeGlobal, false);
+ last_chdir_reason = "autochdir";
shorten_fnames(true);
}
}
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 10d53651cb..dfadd28ebe 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -3487,11 +3487,6 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
}
}
- // If the user didn't specify anything, default to window scope
- if (scope == kCdScopeInvalid) {
- scope = MIN_CD_SCOPE;
- }
-
// Find the tabpage by number
if (scope_number[kCdScopeTabpage] > 0) {
tp = find_tabpage(scope_number[kCdScopeTabpage]);
@@ -3537,12 +3532,13 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr)
case kCdScopeGlobal:
if (globaldir) { // `globaldir` is not always set.
from = globaldir;
- } else if (os_dirname(cwd, MAXPATHL) == FAIL) { // Get the OS CWD.
+ break;
+ }
+ FALLTHROUGH; // In global directory, just need to get OS CWD.
+ case kCdScopeInvalid: // If called without any arguments, get OS CWD.
+ if (os_dirname(cwd, MAXPATHL) == FAIL) {
from = (char_u *)""; // Return empty string on failure.
}
- break;
- case kCdScopeInvalid: // We should never get here
- abort();
}
if (from) {
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 34c3b3889e..62919c98f7 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -7753,6 +7753,7 @@ void post_chdir(CdScope scope, bool trigger_dirchanged)
abort();
}
+ last_chdir_reason = NULL;
shorten_fnames(true);
if (trigger_dirchanged) {
@@ -7870,7 +7871,9 @@ static void ex_pwd(exarg_T *eap)
#endif
if (p_verbose > 0) {
char *context = "global";
- if (curwin->w_localdir != NULL) {
+ if (last_chdir_reason != NULL) {
+ context = last_chdir_reason;
+ } else if (curwin->w_localdir != NULL) {
context = "window";
} else if (curtab->tp_localdir != NULL) {
context = "tabpage";
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 9c065c09f4..b5e1fda9f1 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -789,6 +789,8 @@ extern char_u *compiled_sys;
// directory is not a local directory, globaldir is NULL.
EXTERN char_u *globaldir INIT(= NULL);
+EXTERN char *last_chdir_reason INIT(= NULL);
+
// Whether 'keymodel' contains "stopsel" and "startsel".
EXTERN bool km_stopsel INIT(= false);
EXTERN bool km_startsel INIT(= false);
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 19c820e4dd..7b9081eafa 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -2245,11 +2245,17 @@ int path_full_dir_name(char *directory, char *buffer, size_t len)
}
if (os_chdir(directory) != SUCCESS) {
- // Do not return immediately since we may be in the wrong directory.
- retval = FAIL;
- }
-
- if (retval == FAIL || os_dirname((char_u *)buffer, len) == FAIL) {
+ // Path does not exist (yet). For a full path fail,
+ // will use the path as-is. For a relative path use
+ // the current directory and append the file name.
+ if (path_is_absolute((const char_u *)directory)) {
+ // Do not return immediately since we may be in the wrong directory.
+ retval = FAIL;
+ } else {
+ xstrlcpy(buffer, old_dir, len);
+ append_path(buffer, directory, len);
+ }
+ } else if (os_dirname((char_u *)buffer, len) == FAIL) {
// Do not return immediately since we are in the wrong directory.
retval = FAIL;
}
diff --git a/src/nvim/testdir/test_autochdir.vim b/src/nvim/testdir/test_autochdir.vim
index 0b76828dd7..9ad727241e 100644
--- a/src/nvim/testdir/test_autochdir.vim
+++ b/src/nvim/testdir/test_autochdir.vim
@@ -26,4 +26,42 @@ func Test_set_filename()
call delete('samples/Xtest')
endfunc
+func Test_verbose_pwd()
+ CheckFunction test_autochdir
+ let cwd = getcwd()
+ call test_autochdir()
+
+ edit global.txt
+ call assert_match('\[global\].*testdir$', execute('verbose pwd'))
+
+ call mkdir('Xautodir')
+ split Xautodir/local.txt
+ lcd Xautodir
+ call assert_match('\[window\].*testdir[/\\]Xautodir', execute('verbose pwd'))
+
+ set acd
+ wincmd w
+ call assert_match('\[autochdir\].*testdir$', execute('verbose pwd'))
+ execute 'lcd' cwd
+ call assert_match('\[window\].*testdir$', execute('verbose pwd'))
+ execute 'tcd' cwd
+ call assert_match('\[tabpage\].*testdir$', execute('verbose pwd'))
+ execute 'cd' cwd
+ call assert_match('\[global\].*testdir$', execute('verbose pwd'))
+ edit
+ call assert_match('\[autochdir\].*testdir$', execute('verbose pwd'))
+ wincmd w
+ call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd'))
+ set noacd
+ call assert_match('\[autochdir\].*testdir[/\\]Xautodir', execute('verbose pwd'))
+ wincmd w
+ call assert_match('\[global\].*testdir', execute('verbose pwd'))
+ wincmd w
+ call assert_match('\[window\].*testdir[/\\]Xautodir', execute('verbose pwd'))
+
+ bwipe!
+ call chdir(cwd)
+ call delete('Xautodir', 'rf')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_cd.vim b/src/nvim/testdir/test_cd.vim
index 0bba321ee2..57db0a2544 100644
--- a/src/nvim/testdir/test_cd.vim
+++ b/src/nvim/testdir/test_cd.vim
@@ -215,3 +215,42 @@ func Test_cd_from_non_existing_dir()
cd -
call assert_equal(saveddir, getcwd())
endfunc
+
+func Test_cd_unknown_dir()
+ call mkdir('Xa')
+ cd Xa
+ call writefile(['text'], 'Xb.txt')
+ edit Xa/Xb.txt
+ let first_buf = bufnr()
+ cd ..
+ edit
+ call assert_equal(first_buf, bufnr())
+ edit Xa/Xb.txt
+ call assert_notequal(first_buf, bufnr())
+
+ bwipe!
+ exe "bwipe! " .. first_buf
+ call delete('Xa', 'rf')
+endfunc
+
+func Test_getcwd_actual_dir()
+ CheckFunction test_autochdir
+ let startdir = getcwd()
+ call mkdir('Xactual')
+ call test_autochdir()
+ set autochdir
+ edit Xactual/file.txt
+ call assert_match('testdir.Xactual$', getcwd())
+ lcd ..
+ call assert_match('testdir$', getcwd())
+ edit
+ call assert_match('testdir.Xactual$', getcwd())
+ call assert_match('testdir$', getcwd(win_getid()))
+
+ set noautochdir
+ bwipe!
+ call chdir(startdir)
+ call delete('Xactual', 'rf')
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 9c13264684..4731c2cd41 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -4592,6 +4592,7 @@ void fix_current_dir(void)
do_autocmd_dirchanged(new_dir, curwin->w_localdir
? kCdScopeWindow : kCdScopeTabpage, kCdCauseWindow);
}
+ last_chdir_reason = NULL;
shorten_fnames(true);
}
} else if (globaldir != NULL) {
@@ -4603,6 +4604,7 @@ void fix_current_dir(void)
}
}
XFREE_CLEAR(globaldir);
+ last_chdir_reason = NULL;
shorten_fnames(true);
}
}
diff --git a/test/functional/ex_cmds/cd_spec.lua b/test/functional/ex_cmds/cd_spec.lua
index 283fcf9672..f9cce0deb6 100644
--- a/test/functional/ex_cmds/cd_spec.lua
+++ b/test/functional/ex_cmds/cd_spec.lua
@@ -294,7 +294,16 @@ describe("getcwd()", function ()
command('set autochdir')
command('edit ' .. directories.global .. '/foo')
eq(curdir .. pathsep .. directories.global, cwd())
+ eq(curdir, wcwd())
+ call('mkdir', 'bar')
+ command('edit ' .. 'bar/foo')
+ eq(curdir .. pathsep .. directories.global .. pathsep .. 'bar', cwd())
+ eq(curdir, wcwd())
+ command('lcd ..')
+ eq(curdir .. pathsep .. directories.global, cwd())
+ eq(curdir .. pathsep .. directories.global, wcwd())
+ command('edit')
+ eq(curdir .. pathsep .. directories.global .. pathsep .. 'bar', cwd())
+ eq(curdir .. pathsep .. directories.global, wcwd())
end)
end)
-
-
diff --git a/test/functional/legacy/autochdir_spec.lua b/test/functional/legacy/autochdir_spec.lua
index 466e3ed830..37a94476a0 100644
--- a/test/functional/legacy/autochdir_spec.lua
+++ b/test/functional/legacy/autochdir_spec.lua
@@ -1,10 +1,11 @@
local lfs = require('lfs')
local helpers = require('test.functional.helpers')(after_each)
-local clear, eq = helpers.clear, helpers.eq
-local eval, command = helpers.eval, helpers.command
+local clear, eq, matches = helpers.clear, helpers.eq, helpers.matches
+local eval, command, call = helpers.eval, helpers.command, helpers.call
+local exec_capture = helpers.exec_capture
describe('autochdir behavior', function()
- local dir = 'Xtest-functional-legacy-autochdir'
+ local dir = 'Xtest_functional_legacy_autochdir'
before_each(function()
lfs.mkdir(dir)
@@ -23,4 +24,35 @@ describe('autochdir behavior', function()
eq('Xtest', eval("expand('%')"))
eq(dir, eval([[substitute(getcwd(), '.*[/\\]\(\k*\)', '\1', '')]]))
end)
+
+ it(':verbose pwd shows whether autochdir is used', function()
+ local subdir = 'Xautodir'
+ command('cd '..dir)
+ local cwd = eval('getcwd()')
+ command('edit global.txt')
+ matches('%[global%].*'..dir, exec_capture('verbose pwd'))
+ call('mkdir', subdir)
+ command('split '..subdir..'/local.txt')
+ command('lcd '..subdir)
+ matches('%[window%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd'))
+ command('set autochdir')
+ command('wincmd w')
+ matches('%[autochdir%].*'..dir, exec_capture('verbose pwd'))
+ command('lcd '..cwd)
+ matches('%[window%].*'..dir, exec_capture('verbose pwd'))
+ command('tcd '..cwd)
+ matches('%[tabpage%].*'..dir, exec_capture('verbose pwd'))
+ command('cd '..cwd)
+ matches('%[global%].*'..dir, exec_capture('verbose pwd'))
+ command('edit')
+ matches('%[autochdir%].*'..dir, exec_capture('verbose pwd'))
+ command('wincmd w')
+ matches('%[autochdir%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd'))
+ command('set noautochdir')
+ matches('%[autochdir%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd'))
+ command('wincmd w')
+ matches('%[global%].*'..dir, exec_capture('verbose pwd'))
+ command('wincmd w')
+ matches('%[window%].*'..dir..'[/\\]'..subdir, exec_capture('verbose pwd'))
+ end)
end)
diff --git a/test/functional/legacy/fnamemodify_spec.lua b/test/functional/legacy/fnamemodify_spec.lua
index 6a5538c26f..6262db3a2f 100644
--- a/test/functional/legacy/fnamemodify_spec.lua
+++ b/test/functional/legacy/fnamemodify_spec.lua
@@ -29,7 +29,7 @@ describe('filename modifiers', function()
call assert_equal('test.out', fnamemodify('test.out', ':.'))
call assert_equal('../testdir/a', fnamemodify('../testdir/a', ':.'))
call assert_equal(fnamemodify(tmpdir, ':~').'/test.out', fnamemodify('test.out', ':~'))
- call assert_equal('../testdir/a', fnamemodify('../testdir/a', ':~'))
+ call assert_equal(fnamemodify(tmpdir, ':~').'/../testdir/a', fnamemodify('../testdir/a', ':~'))
call assert_equal('a', fnamemodify('../testdir/a', ':t'))
call assert_equal('', fnamemodify('.', ':p:t'))
call assert_equal('test.out', fnamemodify('test.out', ':p:t'))
diff --git a/test/functional/lua/uri_spec.lua b/test/functional/lua/uri_spec.lua
index 81f1820986..dbfbe2dbfe 100644
--- a/test/functional/lua/uri_spec.lua
+++ b/test/functional/lua/uri_spec.lua
@@ -143,8 +143,8 @@ describe('URI methods', function()
end)
it('uri_to_fname returns non-file scheme URI without authority unchanged', function()
- eq('zipfile:/path/to/archive.zip%3A%3Afilename.txt', exec_lua [[
- return vim.uri_to_fname('zipfile:/path/to/archive.zip%3A%3Afilename.txt')
+ eq('zipfile:///path/to/archive.zip%3A%3Afilename.txt', exec_lua [[
+ return vim.uri_to_fname('zipfile:///path/to/archive.zip%3A%3Afilename.txt')
]])
end)
end)
@@ -186,7 +186,7 @@ describe('URI methods', function()
end)
it('uri_to_bufnr & uri_from_bufnr returns original uri for non-file uris without authority', function()
- local uri = 'zipfile:/path/to/archive.zip%3A%3Afilename.txt'
+ local uri = 'zipfile:///path/to/archive.zip%3A%3Afilename.txt'
local test_case = string.format([[
local uri = '%s'
return vim.uri_from_bufnr(vim.uri_to_bufnr(uri))
diff --git a/test/unit/path_spec.lua b/test/unit/path_spec.lua
index 41954de9be..15ce59747e 100644
--- a/test/unit/path_spec.lua
+++ b/test/unit/path_spec.lua
@@ -54,15 +54,21 @@ describe('path.c', function()
eq(lfs.currentdir(), (ffi.string(buffer)))
end)
- itp('fails if the given directory does not exist', function()
- eq(FAIL, path_full_dir_name('does_not_exist', buffer, length))
- end)
-
itp('works with a normal relative dir', function()
local result = path_full_dir_name('unit-test-directory', buffer, length)
eq(lfs.currentdir() .. '/unit-test-directory', (ffi.string(buffer)))
eq(OK, result)
end)
+
+ itp('works with a non-existing relative dir', function()
+ local result = path_full_dir_name('does-not-exist', buffer, length)
+ eq(lfs.currentdir() .. '/does-not-exist', (ffi.string(buffer)))
+ eq(OK, result)
+ end)
+
+ itp('fails with a non-existing absolute dir', function()
+ eq(FAIL, path_full_dir_name('/does_not_exist', buffer, length))
+ end)
end)
describe('path_full_compare', function()