Problem: a long message is cropped to keep the ruler visible. But when
the message is repeated, it can be written over the ruler, while the
repetition indicator "(1)" is still placed just before the ruler, which
ends up somewhere inside the message.
Solution: currently, long messages are only cropped when setting the
'last' virttext. Make sure this happens after a repeated long message.
Problem: when the search count is displayed, the showcmd virt_text is
set to 11 empty spaces to ensure a consistent distance between search
count and ruler, or screen edge in case of noruler. But when the search
count is removed to make place for a message, the empty dummy showcmd
remains and unnecessarily erases part of the message.
Solution: properly remove showcmd together with search count.
Problem: No concise way to execute a callback with temporarily set
working directory. This might be useful when sourcing nested files to
allow them to assume that current working directory is their root
directory.
Solution: Add `cwd` context to `vim._with().`
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().
Problem:
The dir.lua "-" mapping cannot be easily overridden (because of autocmd
ordering).
Solution:
- Move it to defaults.lua.
- Also to be extra polite: fall back to builtin `-` motion if the user
disabled the `dir.lua` plugin.
- Replace newlines in the current cmdline with NULs when opening cmdwin,
and do the reverse when putting a cmdwin line back into the cmdline.
- Escape control characters with Ctrl-V when feeding cmdline.
Problem:
- If cmdwin window is split, ENTER in one does not close the others.
- If cmdwin is put into a different tabpage via <c-w>T, it stops working
(ENTER does not execute the cmd).
Solution:
- Close the buffer instead of the window.
- In the WinClosed handler, skip `M._cleanup()` unless this is the last
cmdwin window.
Problem:
`:restart` does not preserve window layout, etc.
Solution:
- Change `:restart` to save/restore a session automatically.
- Introduce "bang" variant `:restart!` to restart *without* session
save/restore.
- Introduce `v:startreason`.
- `ZR` maps to `:restart!`.
Problem:
- Lua<=>API roundtrips
- Although we prefer Lua for most business-logic code, doing this
conversion in C makes sense in this case because:
1. setting options is a hot path
2. most of the options logic lives in C
3. the current arrangement is MORE verbose and requires MORE code
Solution:
Move conversion to a C util.
- nvim_set_option_value passes the raw Object (scalar, Array, or Dict)
to `object_as_optval_for()` which flattens it to the canonical `:set`
string and validates the type.
- drop `convert_value_to_vim`, eliminate its roundtrip.
Problem:
`nvim_set_option_value` cannot "update" options similar to `:set opt=`,
`:set opt+=`, etc. The Lua impls of "vim.opt" / "vim.o" have incomplete,
bespoke reimplementations of those operations.
ref #38420
Solution:
- Add `operation` param to `nvim_set_option_value`, which may be "set",
"append", "prepend", or "remove".
- Use this feature to implement `vim.opt` / `vim.o`.
Problem:
Legacy cmdwin set 'buflisted', but new one doesn't.
https://github.com/neovim/neovim/issues/40431#issuecomment-4811593353
'buflisted' useful for:
- "bufferline" style tablines, they usually show only listed buffers.
- some automatic actions can be conditioned on whether a buffer is
listed; 'buflisted' signals that the buffer is "important enough".
Solution:
Set 'buflisted'.
Problem:
After ctrl-f from the cmdline, the last 2 lines of cmdwin are redundant.
Solution:
In `open_cmdwin`, clear the live cmdline so that unwinding it (via
Ctrl_C) does not add it to history.
Problem:
Executing :messages while in cmdwin fails:
Error in "msg_history_show" UI event handler (ns=nvim.ui2):
Lua: …/_core/ui2/messages.lua:699: Invalid 'height': expected positive Integer
stack traceback:
[C]: in function 'nvim_win_set_config'
…/_core/ui2/messages.lua:699: in function 'set_pos'
…/_core/ui2/messages.lua:329: in function 'set_target_pos'
…/_core/ui2/messages.lua:389: in function 'show_msg'
…/_core/ui2/messages.lua:553: in function 'handler'
…/_core/ui2.lua:161: in function 'ui_callback'
…/_core/ui2.lua:210: in function <…/_core/ui2.lua:202>
The bug: when `texth.all` is small (e.g. 0 from a hidden pager whose new
content isn't laid out yet), or when the available height after
subtracting the cmdwin is small, `math.min(min, …)` can yield 0, and
`nvim_win_set_config` rejects `height=0`.
Solution:
Floor at 1.
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).
Problem:
Terminal probes sent with `nvim_ui_send()` can reach more than one stdout TTY
UI. Probes with a known TTY UI owner should not accept `TermResponse`s from
unrelated UI channels.
Solution:
Thread the existing `chan` filter through owned terminal probes. This covers
startup/attach background detection, fallback truecolor detection, and
`vim.tty.query()` forwarding opts to `vim.tty.request()`.
Note: Not every terminal escape path is updated here. I only passed `chan` when
the caller already knows which TTY UI owns the probe. For example, this does
not include:
- (Followup) OSC 52 (system clipboard) detection. It needs to capture the
`UIEnter` channel. Adding `{ chan = ... }` only to the nested query would be
half a fix.
- OSC 52 _paste_ is left global because the provider callback does not have
a UI channel (paste is invoked without a ui channel/tty ui object).
Problem: Attach-time terminal probes cannot distinguish responses from
different attached UIs.
Solution: Identify the UI by RPC channel id in `TermResponse` and make
`vim.tty.request()` filter responses by channel.
Problem: Clearing the screen doesn't clear the "last" virtual text.
Dupe counter virtual text is not increased beyond 1.
Solution: Clear "last" virtual text when clearing the screen.
Restore assignment lost in a previous commit.
Problem: Terminal background and truecolor detection runs only at startup,
gated on a UI being attached. A headless server has no UI then, so
`'background'` and `'termguicolors'` are never detected and remote
UIs ignore the terminal's theme.
Solution: Also (re)detect on UIEnter. The most recently attached terminal
wins; an explicit user value is preserved.
Problem: Writing a message with a large number of newlines
(:echo "foo\n"->repeat(1000000)) takes longer than it has to
(since c973c7ae).
Solution: Accumulate newlines in a single API call when possible.
Problem:
This test is flaky since fff9897ce3 :
FAILED ...Xtest_xdg_terminal/test/functional/terminal/tui_spec.lua @ 4359:
TUI bg color does not trigger OptionSet from automatic background processing
Expected values to be equal.
Expected:
{ true, 0 }
Actual:
{ true, 1 }
stack traceback:
...Xtest_xdg_terminal/test/functional/terminal/tui_spec.lua:4380:
in function <...Xtest_xdg_terminal/test/functional/terminal/tui_spec.lua:4359>
`apply_optionset_autocmd_now` does not emit `OptionSet` during startup:
void apply_optionset_autocmd_now(...) {
// Don't do this while starting up, failure or recursively.
if (starting || errmsg != NULL || *get_vim_var_str(VV_OPTION_TYPE) != NUL) {
return;
}
...
}
but if OSC 11 response arrives AFTER VimEnter, then
`nvim_set_option_value('background',…)` call triggers `OptionSet`.
Solution:
Use `:noautocmd` when setting 'background'.
Per fff9897ce3, OSC11 is not intended to trigger OptionSet.
fix https://github.com/neovim/neovim/issues/40235
Problem: Processing of a very long message may take a long time; there
is no visual feedback of work being done, and no way to abort
processing.
Calculating text height for spill indicator inhibits
performance for very long message.
Solution: Whenever writing part of a message is taking longer than 100ms,
show the first part of the message, while checking for CTRL-C.
Calculate ('wrap'-ed) text height accurately until 'lines',
use line count beyond that.
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.
Problem:
During startup, we manually trigger a useless and misleading `OptionSet`
event, which doesn't set `v:option_*` values (this is a limitation of
`nvim_exec_autocmds`).
ad4bc2d90c/runtime/lua/vim/_core/defaults.lua (L939).
Solution:
The `nvim_exec_autocmds('OptionSet',…)` call does not serve any purpose
since 5cbb9d613b, so just drop it.
Define `:packupdate` and `:packdel` as separate commands instead of a
unified `:pack {subcommand}` because the semantics between the two
commands vary differently enough that it doesn't make sense to combine
them. Additionally, `:pack! update/del` looks bad.
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.
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).
Problem:
Regression from c822a2657c: `vim.wait(0)` does not call `loop_poll`,
so `vim.wait(1)` is needed to "yield" from Lua.
Solution:
- Ensure that `vim._core.loop_poll()` is always called, even when `time=0`.
- Document how to interrupt Lua code (ctrl-c).
ref https://github.com/neovim/neovim/issues/6800
Problem:
Linter missed backtick and double-quote keynames in the quasi-keyset of
the `nvim_create_user_command` docstring.
Solution:
Update the linter to check backtick-surrounded and quote-surrounded key
names.
Problem:
When showing the :connect menu, it is useful to know which servers
are most-recently active. But we don't have a good way to detect that.
Solution:
- Introduce `v:useractive`.
- Include this timestamp in `serverlist({info=true})`.
Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
Signed-off-by: Szymon Wilczek <swilczek.lx@gmail.com>
Problem: Entering the pager fails if <ESC> is remapped to :fclose by user.
Solution: Avoid executing mappings with nvim_feedkeys() that closes expanded cmdline.
Problem:
UI tools and orchestration engines need more context than just raw
socket addresses from serverlist(). Without knowing if a server belongs
to the current instance or knowing its PID, UIs cannot display
meaningful options to users.
Solution:
- Added the `info=v:true` option to `serverlist()`.
- When `info` is requested, it implies `peer=true` and returns a list of
dictionaries (defined as `vim.ServerInfo`) with `addr`, `pid` and
`own`.
- Uses an RPC request to `getpid()` across the socket to fetch the
peer's actual process ID.
Signed-off-by: Szymon Wilczek <swilczek.lx@gmail.com>