25 Commits

Author SHA1 Message Date
Rob Pilling
c57818bb43
fix(ui2): avoid flickering fileinfo messages #41002
## Flicker cause

ui2's `check_targets()` function creates the hidden ui2 windows with this call chain:
```
nvim_open_win()
win_set_buf()
do_buffer()
set_curbuf()
enter_buffer()
```

and `enter_buffer()` sets `need_fileinfo`:

fdc09be03c/src/nvim/buffer.c (L1837-L1839)

This is then picked up by `normal_redraw`:

fdc09be03c/src/nvim/normal.c (L1381-L1385)

The fileinfo message then causes a ui2 window to appear to display it:

fdc09be03c/runtime/lua/vim/_core/ui2/messages.lua (L325-L330)

... which ends up calling `set_pos`, which registers an `on_key` handler:

fdc09be03c/runtime/lua/vim/_core/ui2/messages.lua (L726-L728)

This handler closes the ui2 window when the user presses, for example, `l` (because the user's not focusing said window).
The handler eventually calls `check_targets()`:

fdc09be03c/runtime/lua/vim/_core/ui2/messages.lua (L594-L595)

and `check_targets()` takes us back to the beginning, causing the ui2 window flicker

## Repro

```vim
=require("vim._core.ui2").enable()
set ch=0 shm-=F ve=all
e /tmp/x
```

Then hit `Ctrl-G` to show fileinfo (if not already shown) and hold `l`

## Fix

Effectively surround the ui2 window creating with `:silent`
2026-07-26 17:40:06 -04:00
Justin M. Keyes
9982f6e0e4 refactor(api): omit optional param 2026-07-13 19:44:15 +02:00
Justin M. Keyes
9aa4608401
refactor: introduce nvim_on internally #39883
Problem:
`nvim_create_autocmd` is too verbose and its `callback` requires extra
"nesting".

Solution:
Introduce `nvim_on`. Start using it internally. Then we can get a feel
for how it should look before making it public.
2026-05-20 17:33:01 -04:00
luukvbaal
70c3289290
fix(ui2): unable to configure window height of absolute 1 #39781
Problem:
- Configuring the height of one of the message targets to 1 is
  recognized as 100% of 'lines'.
- Cmdline is expanded for message exceeding 'cmdheight' even if the
  configured height is smaller than or equal to 'cmdheight'.
Solution:
- Recognize a height of 1 as absolute; a decimal number smaller than 1
  is taken as a fraction of 'lines' (replace 1 with 0.999 for the old
  behavior).
- Don't expand the cmdline if the configured height doesn't allow it.
2026-05-14 16:04:58 -04:00
luukvbaal
5f7237f54b
fix(ui2): unable to route by message ID #39734
Problem:  - "bufwrite" message identifier is encoded in the message ID
            of a "progress" kind message (since ff68fd6b); UI2 does not
            allow routing by message ID.
          - No documented way to set a default message target for all
            but a few kinds (without copying all of |ui-messages| kinds
            to cfg.msg.targets).
          - A user adding a message route for the documented empty ""
            kind can result in unexpected behavior.
          - Showing duplicate message (x) indicator in msg and cmd
            targets simultaneously is unsupported.
          - Manually triggering CursorMoved autocommand to add matchparen
            highlighting in the cmdline.
Solution: - Match cfg.msg.targets keys as Lua pattern to a message ID.
          - Recognize "default" as key in cfg.msg.targets, drop the
            undocumented cfg.msg.target field.
          - Don't try to get configured target for "" message kind/trigger.
          - Maintain msg indicator virtual text for the cmd and msg target.
          - Add matchparen highlighting by directly calling the Lua module
            (possible since b813c7e0).
2026-05-11 18:17:04 -04:00
STG
0ea720f281
fix(ui2): error E518 when typing "vim:" in cmdline #39599
Problem: `vim:`, etc. in cmdline are interpreted as modeline, causing error E518.

Solution: Set 'nomodeline' when creating the buffers.
2026-05-06 08:43:01 -04:00
luukvbaal
faa7c15b5a
fix(ui2): don't dismiss expanded messages for non-typed key #39247
Problem:  Invalid check for non-typed key to dismiss expanded cmdline.
          Unable to delay the timer that removes a message from the msg
          window.
Solution: Check for empty string instead of nil to determine whether a
          key is typed.
          Restart the timer if it expires while the user is in the msg
          window. Allow entering the msg window with a mouse click.
2026-04-20 11:38:47 -04:00
Luuk van Baal
607fcfb37a fix(ui2): ensure msg window is visible after closing tab
Problem:  After closing a tabpage while the msg window is showing a
          message, it is hidden while the msg window still contains a
          message.
Solution: Unhide the msg window after entering a tabpage and it still
          contains a message.

Co-authored-by: Linykq <yukunlin590@gmail.com>
2026-04-20 14:20:20 +02:00
luukvbaal
fe986e5dd0
feat(options): add 'winpinned' to pin a window #39157
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>
2026-04-19 20:36:55 -04:00
Christian Clason
e508aa0fa8
fix(ui2): allow empty argument for enable() #38605
Problem: `vim._core.ui2.enable` requires passing an empty table for
default options, unlike other (native) Lua API.

Solution: Initialize `opts` with empty table if `nil` is passed.
2026-03-30 16:47:02 +00:00
Justin M. Keyes
64d55b74d8
docs: news #38464 2026-03-28 09:59:54 -04:00
phanium
ae2829ee35
fix(ui2): ENTER may focus pager in insert/terminal mode #38497
fix(ui2): prevent <CR> from focusing pager in insert/terminal mode

Problem:  <CR> in insert/terminal mode can focus pager unexpectedly.
Solution: Don't enter the pager when <CR> is pressed during expanded
          cmdline in insert/terminal mode.
2026-03-26 13:42:46 -04:00
Justin M. Keyes
a3b48b1054 docs: api, plugins, ui2 2026-03-24 00:14:55 +01:00
luukvbaal
fbac2e5edc
feat(ui2): configure maximum window heights #38392
Problem:
- Window height is set dynamically to match the text height,
  making it difficult for the user to use a different height.
- Cmdwin is closed to enter the pager but still taken into
  account for the pager position, and not restored when
  the pager is closed.
- Dialog pager handler may unnecessarily consume <Esc>.

Solution:
- Add maximum height config fields for each of the UI2 windows,
  where a number smaller than one is a fraction of 'lines',
  absolute height otherwise (i.e. `cfg.msg.pager.height = 0.5`).
- If the cmdwin will be closed to enter the pager, don't try
  to position the pager above it. Re-enter the cmdwin when the
  pager is closed.
- Only add vim.on_key() handler for the dialog paging is actually
  possible.
2026-03-21 10:20:06 -04:00
Luuk van Baal
dff3028fe7 fix(ui2): move windows to current tabpage
Problem:  Windows are closed and re-opened after changing tabpage (and
          might be removed from the current tabpage after 094b297a).
Solution: Ensure windows are on the current tabpage by moving them.
2026-03-19 16:38:44 +01:00
Justin M. Keyes
a3058abf30 docs: deprecate hit-enter 2026-03-11 18:17:46 +01:00
Justin M. Keyes
b8a976afda docs: api, messages, lsp, trust
gen_vimdoc.lua: In prepare for the upcoming release, comment-out the
"Experimental" warning for prerelease features.
2026-03-11 18:00:18 +01:00
Justin M. Keyes
2c5266429c
Merge #37926 msg_show UI event indicates user-interactive 2026-03-10 17:53:11 -04:00
luukvbaal
6275f533d1
fix(ui2): immediately open target windows on new tabpage (#38170)
Problem:  Previous tests for this relied on other events opening the
          targets, which are not guaranteed to happen.
Solution: Open target windows when entering a new tabpage.
2026-03-06 17:32:17 +01:00
Luuk van Baal
875212c5b3 feat(ui2): support routing "typed_cmd" trigger to target
Problem:  Unable to immediately open a typed command in the pager.
Solution: Support mapping msg_show "typed_cmd" trigger in
          cfg.msg.targets (e.g. `targets = { typed_cmd = 'pager' }`).
2026-03-04 15:07:38 +01:00
luukvbaal
32e0d05d53
feat(ui2): configure targets per message kind #38091
Problem:  Unable to configure message targets based on message kind.
Solution: Add cfg.msg.targets mapping message kinds to "cmd/msg/pager".
          Check the configured target when writing the message.
          cfg.msg = { target = 'cmd', targets = { progress = 'msg', list_cmd = 'pager' } }
          will for example use the 'msg' target for progress messages,
          immediately open the pager for 'list_cmd' and use the cmdline
          for all other message kinds.
2026-02-28 08:31:02 -05:00
luukvbaal
844caca881
fix(ui2): multiline/color replaced message, expanded cmdline, error messages #38044
Problem:  - Unintentionally inserting lines for a replaced multiline
          message that also has multiple highlights.
          - Scheduled check to see if the expanded cmdline window was
          entered makes it difficult to keep track of what happens when
          the key pressed to dismiss it results in a message.
          - Reading the first line of an error message should be enough
          notice for something going wrong.
          - "search_cmd" messages should not be shown with 0 'cmdheight'.
          - Unable to configure dynamically changed pager height.
          - Enabling UI2 doesn't make sense with no UIs attached.

Solution: - Only insert a line for the first chunk after a newline.
          - Use getmousepos() to check if the expanded cmdline was
          clicked to enter the pager.
          entering the pager to serve as a configuration interface.
          - Don't expand the cmdline for error messages; user can press g<.
          - Don't show "search_cmd" messages with 'cmdheight' set to 0.
          - Change 'eventignorewin' to ensure WinEnter is fired when
          - Have enable() return early when no UIs are attached.
2026-02-24 17:05:38 -05:00
luukvbaal
29a46a11aa
fix(ui2): don't change configured message target implicitly #37924
Problem:  Implicitly setting message target when 'cmdheight' changes.
Solution: Just use the user configured target. Support "cmd" target
          with 'cmdheight' set to 0.
2026-02-17 13:12:49 -05:00
luukvbaal
16495e6863
fix(ui2): only set dialog on_key callback once #37905
Problem:  vim.on_key() called for each message while cmdline is open.
          Cursor is on a seemingly random column when pager is entered.
          Entering the pager while the cmdline is expanded can be more
          convenient than pressing "g<".
          Pager window is unnecessarily clamped to half the shell height.
          Setting 'laststatus' while pager is open does not adjust its
          dimensions.
Solution: Only call vim.on_key() once when dialog window is opened.
          Ensure cursor is at the start of the first message when
          entering the pager.
          Enter the pager window when "<CR>" is pressed while the
          cmdline is expanded.
          Don't clamp the pager window height.
          Set message windows dimensions when 'laststatus' changes.
2026-02-16 17:11:32 -05:00
luukvbaal
bf68ba40a0
refactor: rename _extui => _core.ui2 #37692
Problem:
_extui module name is confusing and should eventually end up in _core/.

Solution:
Move it there and name it ui2.
2026-02-05 07:45:45 -05:00