aboutsummaryrefslogtreecommitdiff
path: root/test/functional/ex_cmds/cd_spec.lua
Commit message (Collapse)AuthorAge
* fix(cwd): flicker after temp context-switch #41561 #41582Justin M. Keyes2026-08-31
| | | | | | | | | | Problem: `shorten_fnames()` always redraws the statusline/tabline, even if no buffer name changed. Since b296666e a temp context-switch (`win_execute()`, `vim._with{win=}`) restores the CWD, so every such switch flickers the message area. Solution: Redraw only if `shorten_buf_fname()` actually changed a name.
* fix(cwd): stale buffer names after temp context-switch #41433Justin M. Keyes2026-08-22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: 1. `ctx_dirs_restore()` is the only chdir site that doesn't re-shorten buffer names; `post_chdir()`, `update_cwd()` and `do_autochdir()` all call `shorten_fnames(true)`. So after a temp window-context switch that moved the CWD, every buffer's `b_fname` is still relative to the other directory. ui2 renders messages in a float, and entering it is such a switch, so with a `:bcd` in a `BufReadPost` handler 'statusline' "%f" shows ".config/nvim/init.lua" while the CWD is already `~/.config/nvim`, and :write resolves the name against it: ``` E212: Can't open file for writing: no such file or directory ``` 2. `msg_multihl()` leaves `msg_ext_id` pointing at the caller's storage when nothing was emitted (e.g. 'msg_silent'): the reset only ran on a flush that produced chunks. The next message then ships a dead stack frame as its msg_show id. After ":silent write" the id is buf_write()'s `msg_id[MAXPATHL + 32]`: ``` id = "\0\0\0\0\0\0\0\0\29\0(<C6>k\24R\17p<C7><C7><C7>\1\0\0\0..." ``` Solution: 1. `shorten_fnames(true)` after restoring the CWD. Drop `cs_save_sfname`, which was a partial workaround for the same bug. 2. Release the id in `msg_multihl()`, where it is set and the caller's frame is still alive. Stop reading `.data.integer` out of a String union member.
* fix(cwd): nvim_win_set_buf of :bcd buf, changes caller CWD #41329Justin M. Keyes2026-08-15
| | | | | | | | | | | | | | | | | | | | | | | Problem: Setting a :bcd buffer into another window, modifies the caller's CWD. local b = vim.api.nvim_create_buf(true, true) vim.api.nvim_buf_call(b, function() vim.cmd.bcd('..') end) vim.cmd('vsplit') vim.api.nvim_win_set_buf(vim.fn.win_getid(2), b) :echo haslocaldir(0) haslocaldir(-1,0) haslocaldir(-1,-1,0) 0 0 0 :echo getcwd() ==# getcwd(-1,-1) 0 Analysis: `ctx_dirs_save` only saves CWD if it predicts the switch can change it. But win_set_buf() replaces the target window's buffer *after* the switch, which cannot be "predicted" from `ctx_dirs_save`. Solution: Always snapshot whenever the switch enters another window. Skipping `os_dirname` was a micro-optimization.
* fix(cwd): nvim_win_set_buf changes global CWD #41328Justin M. Keyes2026-08-15
| | | | | | | | | | | | | | | | | | | | | Problem: nvim_win_set_buf() on a non-current win, while the current win has a win-local dir, changes the global CWD: :vsplit | lcd .. :call nvim_win_set_buf(other_win, buf) :wincmd l :verbose pwd [global] /parent " expected: the initial cwd Analysis: `globaldir` is where to return when no local dir applies; NULL means the process CWD is already there. Switching to a window with no local dir makes update_cwd() chdir back to `globaldir` and clear it. kCtxKeepCwd restores the process CWD but not that bookkeeping, so the restored window-local dir is mistaken for the global one. Solution: Save/restore `globaldir` with the CWD.
* fix(cwd): :bcd lost by nvim_win_set_buf, nvim_open_win #41218Erdiansyah2026-08-07
| | | | | | | | | | | | Problem: :bcd (buffer-local directory) is not preserved after `nvim_open_win` or `nvim_win_set_buf` Analysis: set_curbuf() ends with update_cwd(), which falls back to os_chdir(globaldir) when the target buffer has no b_localdir. Solution: Pass kCtxKeepCwd to ctx_switch().
* fix(cwd): keep buffer-local dir when re-editing #41215Justin M. Keyes2026-08-07
| | | | | | | | | | | Problem: Re-editing a buffer (`:edit!`, re-reading a dir.lua buffer, etc.) drops its `:bcd` directory, so the CWD falls back to the global one. Whereas other buffer-local state (`b:` vars, local options) survives a reload. Solution: Don't clear buf dir in `buf_freeall()`; `do_ecmd()` calls that when reloading/re-editing. `free_buffer_stuff()` still clears them when a buffer is freed or reused for another file.
* feat(cwd)!: :lcd! (bang), rearrange :bcd/:lcd/… scope precedence #41194Justin M. Keyes2026-08-07
| | | | | | | | | | | | | | | | 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.
* feat(cwd): support explicit chdir (:bcd/:tcd/…) in temp contextJustin M. Keyes2026-08-06
| | | | | | | | | | | | | | | | | | 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.
* fix(:bcd): do not "inherit" buffer-local dirJustin M. Keyes2026-08-04
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Buffer-local CWD (:bcd) is "sticky", similar to window-local CWD (:lcd). But this contradicts one of its main benefits: per-buffer "project root" for LSP, OSC7. Other problems: - A buffer created with :edit/:enew/:new silently inherits b_localdir (and b_prevdir) from the previous buffer. - curbuf_reusable() refuses to recycle a scratch buffer that has `b_localdir`. - After :new/:vnew/:tabnew the CWD sticks to previous buffer's `b_localdir` even though the new curbuf has none, so :new is not equivalent to ":split | enew", and getcwd() disagrees with haslocaldir(). - Requires "which buffer spawned this buffer" semantics that no other buffer-local state has. Solution: Drop sticky/inherit behavior of buffer-local CWD (:bcd). - do_ecmd: always apply the new curbuf's dir (`fix_current_dir`), like `do_autochdir` already does. :tabnew from a :bcd buffer now reverts to global CWD (and fires DirChanged), same as :tabnew from a :lcd window. - curbuf_reusable(): recycling a scratch buffer frees its b_localdir. To get sticky/inherit behavior of CWD, use `:lcd`.
* fix(cwd): validate getcwd(…, -1)Justin M. Keyes2026-08-04
|
* refactor(editor): cleanup change-directory (:bcd) logicJustin M. Keyes2026-08-04
|
* feat(editor): `:bcd` changes buffer-local directorysaher2026-08-04
| | | | | | | | | | | | | | | | | | Problem: No way to set a buffer-local directory. Use-cases: - "Root dir" for LSP (and the "project" concept). - `:terminal` OSC 7 Solution: Add `:bcd` command. - Extend `getcwd()` to take a third arg; `getcwd(-1, -1, bunfr)` returns the buffer-local working directory. - Buffer-local directories have less priority than window-local ones, and more priority than tab-local ones. Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* test(harness): migrate away from magic globalsJustin M. Keyes2026-07-21
| | | | | | | | | | | | | | | | | | | | | Problem: The magic globals `it`, `describe`, etc., are more trouble than they are worth. - Hooking into `after_each` requires `getfenv()` hacks. - They confuse luals/emmylua, because the top-level `.luarc.json` isn't merged with `test/.luarc.json` (apparently a luals limitation?) - They totally defeat discoverability because the user just has to "know" about the various magic symbols. So they harm DX, which means they serve no purpose at all. Solution: - Expose the test API from `testutil`, so tests can call `t.it()`, `t.describe()`, etc., in the conventional way. - Drop `getfenv()` hacks. - Drop the `setfenv()` injection in `load_chunk`. - Drop `test/_meta.lua`.
* refactor(test): drop deprecated exc_exec #39242Justin M. Keyes2026-04-20
|
* test: add reasons to some skipped tests (#37632)zeertzjq2026-01-31
|
* test: improve test conventionsdundargoc2024-04-23
| | | | | | | | | Specifically, functions that are run in the context of the test runner are put in module `test/testutil.lua` while the functions that are run in the context of the test session are put in `test/functional/testnvim.lua`. Closes https://github.com/neovim/neovim/issues/27004.
* refactor(test): inject after_each differentlyLewis Russell2024-04-10
|
* test: improve test conventionsdundargoc2024-04-08
| | | | Work on https://github.com/neovim/neovim/issues/27004.
* test: use vim.mpack and vim.uv directlyLewis Russell2024-01-12
|
* refactor: format test/*Justin M. Keyes2024-01-03
|
* test: replace lfs with luv and vim.fsdundargoc2023-04-04
| | | | | | test: replace lfs with luv luv already pretty much does everything lfs does, so this duplication of dependencies isn't needed.
* test: simplify platform detection (#21020)dundargoc2022-11-22
| | | | | Extend the capabilities of is_os to detect more platforms such as freebsd and openbsd. Also remove `iswin()` helper function as it can be replaced by `is_os("win")`.
* test: introduce skip() #21010dundargoc2022-11-13
| | | | | | | This is essentially a convenience wrapper around the `pending()` function, similar to `skip_fragile()` but more general-purpose. Also remove `pending_win32` function as it can be replaced by `skip(iswin())`.
* docs: typo fixes (#17859)dundargoc2022-04-15
| | | | | | | | | | Co-authored-by: Elias Alves Moura <eliamoura.alves@gmail.com> Co-authored-by: venkatesh <shariharanvenkatesh@gmail.com> Co-authored-by: zeertzjq <zeertzjq@outlook.com> Co-authored-by: Vikas Raj <24727447+numToStr@users.noreply.github.com> Co-authored-by: Steve Vermeulen <sfvermeulen@gmail.com> Co-authored-by: Evgeni Chasnovski <evgeni.chasnovski@gmail.com> Co-authored-by: rwxd <rwxd@pm.me> Co-authored-by: casswedson <58050969+casswedson@users.noreply.github.com>
* vim-patch:8.2.3618: getcwd() is unclear about how 'autochdir' is usedzeertzjq2021-11-19
| | | | | | | Problem: getcwd() is unclear about how 'autochdir' is used. Solution: Update the help for getcwd(). Without any arguments always return the actual current directory. (closes vim/vim#9142) https://github.com/vim/vim/commit/851c7a699ae00bdc14a4db874cf722b7b7393b53
* options: properly reset directories on 'autochdir' (#9894)Marco Hinz2019-04-13
| | | Fixes https://github.com/neovim/neovim/issues/9892
* Resolve issues mentioned in PR reviewJan Edmund Lazo2018-02-19
|
* test: enable ex_cmds/cd_spec.lua on WindowsJan Edmund Lazo2018-02-19
|
* functests: Replace execute with either command or feed_commandZyX2017-04-09
| | | | | | | | | | Hope this will make people using feed_command less likely: this hides bugs. Already found at least two: 1. msgpackparse() will show internal error: hash_add() in case of duplicate keys, though it will still work correctly. Currently silenced. 2. ttimeoutlen was spelled incorrectly, resulting in option not being set when expected. Test was still functioning somehow though. Currently fixed.
* CI: test: Avoid QuickBuild hang. (#5330)Justin M. Keyes2016-09-12
| | | Delete the CWD using nvim instead of the external lua/test runner process.
* getcwd(): Return empty string if CWD is invalid. #5292HiPhish2016-09-04
| | | | | | | | | | Closes #5291 Restores behaviour identical to Vim. If the user calls the VimScript function 'getcwd()' and the working directory cannot be found (for example because the directory has been deleted since the last time it was used) an empty string needs to be returned instead of throwing an error.
* tchdir: New tab should inherit CWD. (#5227)Alejandro Sanchez2016-09-04
| | | | When a new tabpage gets created it will copy the local working directory of the previous one, if there is any.
* Mark some functional tests as pending in WindowsRui Abreu Ferreira2016-08-26
|
* functests: Check logs in lua codeZyX2016-06-10
| | | | | | It is otherwise impossible to determine which test failed sanitizer/valgrind check. test/functional/helpers.lua module return was changed so that tests which do not provide after_each function to get new check will automatically fail.
* test/functional: cd_spec: Add tests for {getcwd,haslocaldir}(-1, -1)James McCoy2016-06-01
|
* test/functional: cd_spec: Add tests for using explicit argsJames McCoy2016-06-01
|
* test/functional: cd_spec: Use named keys for directories tableJames McCoy2016-06-01
| | | | | | The directories table contains the names of the expected directory names for varying scopes of the :cd tests. Using named indexes, instead of numbered, makes the test more readable.
* test/functional: Allow arbitrary arguments to cwd/lwd functionsJames McCoy2016-06-01
| | | | | | Build wcwd/tcwd and wlwd/tlwd on top of the reworked cwd/lwd functions. This will allow for easier testing of `getcwd()`/`haslocaldir()` in arbitrary windows and/or tab pages.
* test/functional: fix a dependency on the previous test suiteJohn Szakmeister2016-05-06
| | | | | | | While trying to debug an issue, I discovered that the tests for illegal arguments depended on the prior suite having run and started a session. Let's remove that unintentional dependency by starting our own session before each test.
* test/functional: prefix the cd command with silent to prevent hangingJohn Szakmeister2016-05-06
| | | | | In longer directory paths, the test can hang waiting for the user to hit enter to continue. Let's use the silent prefix to avoid this.
* Satisfy testlint.KillTheMule2016-04-28
| | | | For that, make luatest ignore the preload.lua files.
* tcd: doc, error messagesJustin M. Keyes2016-04-21
|
* Implement tab-local working directory feature.HiPhish2016-04-20
New ex commands: 'tcd', 'tchdir' Changed Vimscript functions: 'haslocaldir', 'getcwd' The ex-commands ':tcd' and ':tchdir' are the tab-local equivalents of ':lcd' and ':lchdir'. There are no new Vimscript functions introduced, instead the functions 'haslocaldir' and 'getcwd' take in optional arguments. See the documentation for details Since there is now different levels of local directory a simple boolean at source level is no longer sufficient; a new enumeration type is used for the scope-level from now on. The documentation has been accommodated for these new commands and functional tests have been written to test the feature.