aboutsummaryrefslogtreecommitdiff
path: root/test/functional/api/window_spec.lua
Commit message (Collapse)AuthorAge
* fix(api): leaked error message in nvim_win_set_buf() #41688Volodymyr Chernetskyi2026-09-04
| | | | | | | | | | | | | | Problem: Both handle lookups write into the same `Error` before either one is checked, and `api_set_error()` unconditionally `xmalloc`s `err->msg` without freeing what is already there. When both handles are invalid, the message allocated for the window is silently overwritten by the one for the buffer and leaked. Solution: Check the window before looking up the buffer. As a side effect the reported error no longer names the buffer when the window was wrong too. AI-assisted
* fix(cmdwin): allow a user to switch to other buffers #41199Rob Pilling2026-08-28
|
* test: fix wrong order of args to eq(), neq() #41499zeertzjq2026-08-26
|
* refactor(ruler)!: replace C implementation with 'rulerformat' expressionSébastien Hoffmann2026-08-04
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: The default 'ruler' is implemented in C instead of the 'statusline' DSL. Solution: Replace the C implementation with a default 'rulerformat' expression. This is a continuation of #1248 and #33036. Advantages: - configuration is more discoverable, the default being a useful example - users and plugins can augment the default - code reuse and less C code to maintain - ui2: due to the use of an item group with `minwid`, it can expand instead of truncating when the content gets too long, which is particularly useful for locales with long translations of Top/Bot/All Implementation details: As is the case for 'statusline', when trying to set 'rulerformat' to an empty string, the default expression is restored instead, mimicking how previously the default C implementation would have been activated. Just like before, `:set rulerformat=` and `:set rulerformat&` have the same effect, and the ruler is disabled with `:set noruler`. The default expression uses an item group with `%=`, unlike the fallback in the previous default statusline `%-14.(%l,%c%V%) %P`, because the total width and how it is configured is immediately clear without documentation, it is a more useful pattern in general that works when both sides have flexible width, and it also works for vim, which is useful for configuration sharing/reuse. A truncation marker `%<` is added at the end to mimic how at small screen widths, the scroll percentage would disappear first, so that the cursor position can remain fully visible. BREAKING CHANGES: - `&rulerformat` can no longer be set to an empty string - ui2: the default ruler is no longer of fixed width, but can expand - at very small screen widths (< 36 columns) - ui2: it will no longer try to shrink white-space before truncating - it truncates gradually from the right, whereas previously, the scroll percentage would disappear all at once - l10n can no longer add a space after the comma between line and column (this was only done for one language: Ukrainian)
* fix(ruler)!: consistent width in last line and statuslineSébastien Hoffmann2026-08-04
| | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Traditionally, the ruler in the last line is one cell shorter than in the statusline, leaving the last cell of the screen blank. According to code comments, this is in order to prevent unwanted scrolling on "some" (unspecified, but presumably ancient) terminals. Berkeley vi is more specific in its `vs_modeline` function: dumb terminals with hardware scroll, SunOS 4.1.1 and Ultrix 4.2 curses. (n)curses still has a similar limitation in `(w)addstr`, but apparently only for historical reasons. Maintaining the different widths leads to awkward inconsistencies when the ruler is configured with 'rulerformat', except for the special case where it contains a top-level `%=`. Shifting the ruler in the last line to the left would be a solution, but the empty cell at the end doesn't seem to be relevant anymore. Solution: extend the ruler in the last line all the way to the right edge of the screen, just like in the statusline. The exact same amount of place will be available to the rest of the UI as before. BREAKING CHANGE: - the default ruler width is now 18 cells - the last cell of the screen is no longer empty Closes #41076
* 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`.
* test: fix typo (#40750)zeertzjq2026-07-15
|
* fix(floatwin): don't use same window as altwin (#40748)zeertzjq2026-07-15
| | | | Fixes a regression from #34486 Fix #40745
* fix(startup): respect enter for windows created in startup scripts #37287glepnir2026-07-12
| | | | | | | | | Problem: When a split window is created from the init script using nvim_open_win() with enter=false, the current window focus is not preserved. The cursor incorrectly moves into the newly created split during startup. Solution: Save curwin before the iteration loop in create_windows(), and restore it after the loop. also update edit_buffers() to use curwin instead of firstwin.
* refactor(ctx): ctx_restore_curwin #40667Justin M. Keyes2026-07-10
| | | | | | | | unify context-switching logic. 1. `prevwin` is now restored for all targets (was buf-only). - add a `nvim_win_call` test. 2. The buf-found "restore the shown buffer" dance no longer depends on the origin window: it runs even if the callback closed the origin.
* fix(api): nvim_win_resize tweaks #40596Justin M. Keyes2026-07-05
|
* Merge #40520 nvim_win_resizeJustin M. Keyes2026-07-05
|\
| * feat(api): add nvim_win_resize()XiaowenHu962026-07-05
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Ref #6645 Problem: When a window is resized it takes space from the window right/below first, and only falls back to the window left/above when there is no more room. Sometimes a user wants the space to come from a specific direction. Solution: Add nvim_win_resize(win, width, height, {anchor}) which resizes a window with a choosable anchor edge, letting a window grow leftwards or upwards by taking space from the window to the left or above first. The default anchor reproduces nvim_win_set_width()/nvim_win_set_height().
* | feat(cmdwin): implement cmdwin as a normal buf+winJustin M. Keyes2026-06-25
|/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: cmdwin (the `:q` cmdline buffer) has various limitations which require special-casing all over the codebase. Besides complicating the code, it also breaks async plugins if they try to create buffers/windows after some work is done, if the user happens to open cmdwin at the wrong the moment: Lua callback: …/guh.nvim/lua/guh/util.lua:531: E11: Invalid in command-line window; <CR> executes, CTRL-C quits stack traceback: [C]: in function 'nvim_buf_delete' …/guh.nvim/lua/guh/util.lua:531: in function <…/guh.nvim/lua/guh/util.lua:526> Solution: Just say no to "inception". Reimplement cmdwin as a normal buffer+window. All of the cmdwin contortions (in both core, and innocent plugins) exist literally only to support "inception": recursive cmdwin-in-cmdline-things, like `<c-r>=`, `/`, search-during-substitute, `:input()`, etc. So we just won't support that (though I have a potential plan for that later, which I call "modal parking lot"). The benefit is that plugins, and core, no longer have to care about cmdwin. BONUS: - mouse-drag on vertical separators works (it only worked for horizontal/statusline before) - inccommand-in-cmdwin now works correctly, for free (thus don't need #40077). POTENTIAL FOLLOWUPS - Drop `CHECK_CMDWIN` ("E11: Invalid in command-line window"), allow chaos. - Unify `BUFLOCK_OK` / `LOCK_OK` ? DESIGN: - Eliminate lots of C globals, `EX_CMDWIN`, etc. - `text_locked()` no longer reports true for cmdwin. - cmdwin = a normal window with 'winfixbuf', 'bufhidden=wipe', 'buftype=nofile'. Invariants come from those options rather than special cases throughout the codebase. - `nv_record` for q:/q//q? calls Lua `nlua_call_vimfn("vim._core.cmdwin", …)`. No `K_CMDWIN` / cmdline-reader detour. - `cedit_key` (`c_CTRL-F`) schedules a deferred event that calls `vim._core.cmdwin.open(type, content, pos)` and returns `Ctrl_C` so the in-flight cmdline cancels. Reader state is not serialized; instead the captured `(type, line, col)` is replayed via `nvim_feedkeys(type..line.."<CR>", "nt", …)` after user confirms. - On confirm/cancel: `<CR>` / `<C-C>` calls into Lua which closes the window and re-feeds the cmdline. BREAKING CHANGES: - Expression-register cmdline (`<C-R>=` from insert-mode) no longer supports cmdwin. Same applies to `input()` / `inputlist()` (already covered by `text_locked`). - Usage of cmdwin in macros/mappings will probably break (assuming they ever worked).
* fix(api): regressions with lua return values #39837bfredl2026-05-18
| | | | | fixes #39834 fixes #39833 fixes #39851
* refactor: group nvim_buf_call, nvim_win_call tests #39828Justin M. Keyes2026-05-17
|
* feat(api): nvim_buf_call, win_call can has multiple return values #39801bfredl2026-05-17
| | | | | | from the "because we can and it is not much code" department. (diffcount excluding tests is actually negative) fixes https://github.com/neovim/neovim/issues/39636#issuecomment-4397141270
* feat(options): add 'winpinned' to pin a window #39157luukvbaal2026-04-19
| | | | | | | | | | | | | | Problem: - Unable to "pin" a window to prevent closing without specifically being targeted. - :fclose closes hidden windows (even before visible windows). Solution: - Add 'winpinned' window-local option. When set, window is skipped by :fclose and :only. Pin the ui2 cmdline window (which should always be visible), so that it is not closed by :only/fclose. - Skip over hidden (and pinned) windows with :fclose. Co-authored-by: glepnir <glephunter@gmail.com>
* fix(api): use standard error messagesJustin M. Keyes2026-03-16
|
* fix(api): improve external window validationSean Dewar2026-03-14
| | | | | | | | | | | | | | | | | Problem: "win" is allowed in external window configs in some cases. External window converted to normal float can't move tabpages in one nvim_win_set_config call. External window can't be turned into a normal split. Solution: disallow setting "win" for external windows. Allow external window to move tabpages, which turns it non-external. Allow external window to be turned into a (non-external) split. parse_win_config has more validation issues from not considering the window's existing config enough (not from this PR). For example, zindex can be set for an existing split if "split"/"vertical" isn't given, despite intending for that to be an error. Plus the logic is confusing. It could do with a refactor at some point...
* fix(api): disallow moving window between tabpages in more casesSean Dewar2026-03-14
| | | | | | | | | | | | | | | | Problem: more cases where it may not be safe to move a window between tabpages. Solution: check them. Rather speculative... I haven't spend much time looking, but I didn't find existing code that sets these locks to skip checking win_valid. (what I did find called it anyway, like in win_close) Still, I think it's a good precaution for what future code might do. If the fact that nvim_win_set_config *actually* moves windows between tabpages causes unforeseen issues, "faking" it like ":wincmd T" may be an alternative: split a new window, close the old one, but instead also block autocmds, copy the old window's config, and give it its handle?
* feat(api): nvim_win_set_config can move split to other tp as floatwinSean Dewar2026-03-14
| | | | | | | Problem: not possible for nvim_win_set_config to convert a split to a floatwin, then move it to another tabpage in one call. Solution: allow it.
* fix(winfloat): last_status when changing split to floatwinSean Dewar2026-03-14
| | | | | | | | | | | | Problem: converting a split to a floatwin may not remove the last statusline when needed. (e.g: 'ls' is 1) Solution: call last_status/win_comp_pos in win_new_float, after win_remove. Also fix float_pos formatting for screen snapshots so it doesn't give a nil error for external windows. Not an issue from this PR.
* fix(api): relax config validation for "win"Sean Dewar2026-03-14
| | | | | | | | | | | | | | | | Problem: only possible to move floats between tabpages if relative=win, which has the restrictive effect of also anchoring it to the target window. Solution: allow "win" without "relative" or "split"/"vertical". Only assume missing "win" is 0 if relative=win is given to maintain that behaviour. (or when configuring a new window) Also add an error when attempting to change a split into a float that's in another tabpage, as this isn't actually supported yet. (until the next commit) Maybe this could do with some bikeshedding. Unclear if "win" should require "relative" to be given, like with "row"/"col"; this can be annoying though as specifying "relative" requires other fields to be given too.
* refactor(api): cleanup, more comments, more tests, newsSean Dewar2026-03-14
| | | | | | | | | - Factor out logic to keep nvim_win_set_config clean. - Clean up a few things, remove redundant logic, reflow some lines. - Add some more comments where appropriate. - Don't consider negative "win", as that's only relevant for splits. - Add more test coverage. - Add news.txt entry.
* feat(api): nvim_win_set_config can move floatwin to another tabpageglepnir2026-03-14
| | | | | | | | Problem: nvim_win_set_config can't move floating windows to different tab pages. Solution: allow it. Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
* fix(window): don't leak fold memory with style=minimal #38287Sean Dewar2026-03-14
| | | | | | Problem: discarding saved option values in the WinInfo of closed style=minimal windows leaks memory. Solution: also free the nested folds.
* Merge #38206 nvim_win_set_configJustin M. Keyes2026-03-09
|\
| * fix(api): unnecessary errors when not moving splitSean Dewar2026-03-09
| | | | | | | | | | | | | | Problem: nvim_win_set_config may raise unnecessary errors when not moving a split. Solution: skip checks related to moving when only maybe resizing a split.
| * fix(api): redraw after setting minimal styleSean Dewar2026-03-09
| | | | | | | | | | | | | | | | Problem: No explicit redraw after setting style=minimal in nvim_open_win or nvim_win_set_config, which may cause it to appear like it's not set. Solution: call changed_window_setting after applying the style, which should be enough for these options.
* | fix(api): don't re-apply minimal style if unchanged #38152Sean Dewar2026-03-09
|/ | | | | | | | | | Problem: nvim_win_set_config with style=minimal re-applies option values even if the new style is unchanged from the old. This may be undesirable after #38122. Solution: don't bother in this case. See https://github.com/neovim/neovim/pull/38122#issuecomment-3996994189. A reversal of https://github.com/neovim/neovim/pull/22865#discussion_r1161598973 so its associated test has been updated.
* fix(api): merge split window config only on successSean Dewar2026-03-08
| | | | | | | | | | | | | | | Problem: nvim_win_set_config may merge configs despite failing to configure a split, and without applying necessary side-effects (like setting style=minimal options). Plus, autocommands may apply a different config after the merge, causing side-effects to apply for an outdated config. Solution: merge configs last, only on success. Include fields only relevant to splits. Properly set _cmdline_offset for splits. Maybe better to disallow _cmdline_offset for splits instead, as the pum is relative to cmdline_row anyway? (I didn't want to change behaviour too much) Also use expect_unchanged in an unrelated test to quash a warning.
* fix(api): style=minimal not applied immediately for unmoved splitSean Dewar2026-03-08
| | | | | | | | | Problem: nvim_win_set_config with style="minimal" does not take immediate effect when a split is not moved. Solution: don't skip nvim_win_set_config's epilogue when only a resize may be needed. De-duplicate resize logic and remove unnecessary redraw. (win_set*_win already handles that)
* fix(api): return "style" in nvim_win_get_config() #38122Sean Dewar2026-03-03
| | | | | | | | | | Problem: nvim_win_get_config() does not return a window's "style". Solution: always include it, and document `style=""`. Always included so it can be used reciprocally with nvim_open_win() or nvim_win_set_config(). (otherwise the config of a window with kWinStyleUnused will not unset the kWinStyleMinimal style of another window if passed to nvim_win_set_config, for example)
* fix(api): preserve WinConfig style when converting float to split #37264glepnir2026-02-12
| | | | | | | | | | Problem: When a float window with style='minimal' is converted to a split window and then changes buffer, the minimal style options get overridden. This happens because merge_win_config() clears the style field, so get_winopts() doesn't know to re-apply minimal style after restoring options from the buffer's wininfo. Solution: Save and restore the style field when clearing the config during float-to-split conversion.
* fix(api): open_win leak from naughty autocommandsSean Dewar2025-12-21
| | | | | | | | Problem: error set by win_set_buf may leak if autocommands immediately close the new window. Solution: free the error set by win_set_buf. (prefer nvim_open_win's error as it's more important and will cause 0 to be returned)
* fix(api): ignore split_disallowed when opening a floatSean Dewar2025-12-21
| | | | | | | | | | | | | | | | | Problem: split_disallowed seemingly exists to prevent issues from changing frames to accomodate a split window, which doesn't apply to floats. Solution: remove the restriction for nvim_open_win, but only for floats. (continue to check b_locked_split though) NOTE: like before, the buffer we check b_locked_split for may not actually be the target buffer "buf", as the later call to win_set_buf can fail to switch to "buf" due to autocommands. (among other things) Maybe we could attempt to close the new window in that case (or switch to a different buffer if that also fails), but this is safer. (and simpler) Fixes #36857 (and possibly some spurious E242s I've observed from extui)
* docs: misc, build, lspJustin M. Keyes2025-11-22
|
* feat(api): nvim_win_set_config accepts unchanged "noautocmd" #36463glepnir2025-11-18
| | | | | | Problem: Cannot reuse same config with noautocmd for both window creation and updates, even when value is unchanged. Solution: Only reject noautocmd changes for existing windows.
* fix(api): nvim_open_win default to half-size for splits (#36088)Sean Dewar2025-10-08
| | | | | | | | Problem: after #35601, nvim_open_win incorrectly attempts to set the size of a split window to 0 if it wasn't specified. Solution: only attempt to set the size again if it was actually specified. This has the effect of defaulting to half the size of the parent window (or it may be equalized with other windows to make room), like before. Fix #36080
* fix(api): nvim_open_win respects requested split window size (#35601)glepnir2025-10-04
| | | | | | | | | Problem: requested window size passed to nvim_open_win for splits may be ignored by win_split_ins if it decides to forcefully equalize window sizes instead (e.g: in an attempt to make room for the new window). Solution: try to set the size again if it differs from what was requested. Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
* fix(api): crash when moving curwin to other tabpage #35679glepnir2025-09-08
| | | | | | | | | | | Problem: nvim_win_set_config may crash when attempting to move curwin to a different tabpage if there is no other non-float available to switch to. Solution: fix the crash. Fix ONE_WINDOW checks in winframe_find_altwin and win_altframe to consider floating windows by instead using one_window. Allow one_window to consider non-current tabpages. We can use one_window in win_close_othertab now to also better reflect its use in win_close. Co-authored-by: Sean Dewar <6256228+seandewar@users.noreply.github.com>
* fix(api): win_set_config error message for splitting from a float #35650Sean Dewar2025-09-06
| | | | | | | Problem: after #34287 nvim_win_set_config no longer errors when attempting to split from a floating window only if "win" is 0. Solution: fix the regression, reduce the scope of "parent" and similar checks to only where it's currently used and add test coverage for the errors.
* fix(api): do not allow opening float to closing bufferSean Dewar2025-07-22
| | | | | | | | | | | | | | | | | | | | | | | | | Problem: no check for nvim_open_win opening a new floating window into a closing buffer, which can lead to crashes. Solution: call check_split_disallowed; opening a new float semantically splits from a window, so the same problems as regular splits apply. Also restore the error if switch_win_noblock in win_set_buf fails (may not be possible to hit this, but win_set_buf can silently succeed there since #31595). As the lock check applies to curbuf (not the target buffer) this may feel a bit restrictive, though this isn't different to how things like ":split" or nvim_open_win with "split = true" works when targeting a different buffer. Only checking the target buffer's lock will cause issues if win_set_buf doesn't end up in the target buffer for whatever reason. Maybe we could consider checking the lock of the buffer after win_set_buf and close the window if it's locked (maybe a bit fiddly, especially as closing a window can fail...), or make the open + switch operation more atomic, like how Vim does for its popup windows..? It also used to be the case that win_set_buf would set an error if autocommands sent us to a different buffer than what was requested, but #31595 appears to have also changed that... I haven't touched that here.
* fix(window): restore b_nwindows if win_close_othertab keeps windowSean Dewar2025-07-22
| | | | | | | | | | | | | | Problem: can't accurately know if close_buffer directly (e.g: not via autocmds) decremented b_nwindows. This can cause crashes if win_close_othertab decides to keep the window after calling close_buffer (if it did not free the buffer), as b_nwindows may remain out-of-sync. Solution: change the return value of close_buffer to accurately depict whether it decremented b_nwindows. Check it in win_close_othertab to avoid a crash. Similar issues may exist in other places that call close_buffer, but I've not addressed those here (not to mention only one other place even checks its return value...)
* fix(window): handle closing the only non-float in other tabpageSean Dewar2025-07-22
| | | | | | | | | | | | | | Problem: No check for closing the only non-floating window in a non-current tabpage that contains floats. This can lead to a tabpage that contains only floats, causing crashes. Solution: Copy the relevant check from win_close to win_close_othertab. Fix some uncovered issues. Closes #34943 Fixes #31236 Co-authored-by: glepnir <glephunter@gmail.com>
* fix(window): don't enter unfocusable or hidden prevwin (#34486)luukvbaal2025-06-14
| | | | | | Problem: When closing a floating window, the next window to be entered may be unfocusable or hidden. Solution: Don't enter prevwin when it is unfocusable or hidden. Enter firstwin instead (like for when prevwin is no longer valid).
* vim-patch:9.1.1361: [security]: possible use-after-free when closing a ↵Sean Dewar2025-05-04
| | | | | | | | | | | | | | | | | buffer (#33820) Problem: [security]: Possible to open more windows into a closing buffer without splitting, bypassing existing "b_locked_split" checks and triggering use-after-free Solution: Disallow switching to a closing buffer. Editing a closing buffer (via ":edit", etc.) was fixed in v9.1.0764, but add an error message and check just "b_locked_split", as "b_locked" is necessary only when the buffer shouldn't be wiped, and may be set for buffers that are in-use but not actually closing. (Sean Dewar) closes: vim/vim#17246 https://github.com/vim/vim/commit/6cb1c828406dcbb9b67ee788501b94f3a0bac88a
* feat(options): default statusline expression #33036Shadman2025-04-21
|