aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/api/vim.c
Commit message (Collapse)AuthorAge
* multicursor: v:cascading #42289Evgeni Chasnovski8 days
| | | | | Problem: No way to check if cascade is in action. Solution: Add `v:cascading` variable.
* feat(api): nvim_chan_set()Justin M. Keyes11 days
| | | | | | | | | | | | | | | | | | | Problem: Only the stdio channel can "own" a server (self-exit on close). After :restart the TUI reconnects over a socket, so the restarted server does not have "self-exit" behavior when the channel closes (e.g. by UI disconnect, host-terminal close, etc.), which leaves a dangling server. Solution: - Introduce `nvim_chan_set`. (`nvim_set_client_info` doesn't fit: exposing it to Lua would require a `channel` param, which is not backwards-compatible, plus it's awkward because it doesn't merge info.) - Broadcast per-channel properties in the "restart" UI event as an opaque dict (a potentially useful pattern for other UI-events in the future). - UIs are expected to restore the channel properties on restart. - `nvim_get_chan_info()` reports "detach". - Remove `nvim__chan_set_detach()`.
* fix(lua): regression with `print()` in headless modebfredl14 days
| | | | | | | | | This is a bunch of hacks so we can override msg_puts_printf specifically while still allowing redirecting and "normal" message flow to happen, as this still has observable side-effects (even with no screen attached, screenstring() is still valid..) fixes #42218
* refactor(multicursor)!: drop nvim_mcursor #42156Justin M. Keyes2026-09-30
| | | | | | | | | | | | | | Problem: `nvim_mcursor` is not fully baked, and not strongly motivated, currently. The main programmatic interface for cursors is the "nvim.multicursor" extmarks namespace. Solution: Drop `nvim_mcursor`. Add an internal hook so that multicursor can react when extmarks are added to the "nvim.multicursor" namespace. TODO: If extmarks/namespaces are clumsy to work with, we should _fix that_ rather than adding wrappers.
* fix(api): correct Lua command and completion typesLewis Russell2026-09-28
| | | | | | | | | | | Problem: Command inputs and parsed modifiers have different optional fields, and completion window IDs are annotated as floating-point values. Solution: Separate modifier input and return types, correct integer IDs, and update the metadata generators and their output. AI-assisted
* refactor(option): simplify error buffer handlingLewis Russell2026-09-21
| | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Option validators and setters repeatedly pass error buffers and their sizes separately. Some setters return messages in static storage. Solution: - Add CharBuf for borrowed writable storage, with its length including space for a terminating NUL. - Move option error buffers to the callers that report errors. Preserve existing buffer sizes, truncation, and calls that do not need a message. - Consolidate option error formatting and the duplicated code that lists valid option values. - Return error messages directly from do_one_set_option(). - Remove unused arguments from get_option_newval() and set_option_value_for(). - Handle legacy TTY assignments in the existing callers and remove the redundant compatibility wrapper. - Reuse CharBuf for Tree-sitter query errors. - Pass CharBuf through the statusline and statuscolumn builders, retaining the buffer sizes provided by their callers, including title formatting. AI-assisted
* fix(api): leaked error message in nvim_eval_statusline() #41690Volodymyr Chernetskyi2026-09-04
| | | | | | | | | | | | Problem: `find_window_by_handle()` returns NULL only after `VALIDATE_INT` has already set `err`, so the `api_set_error()` that followed allocated a second message over the first pointer and leaked it. Solution: Drop the redundant call and keep the helper's message, which is already set and better worded. AI-assisted
* feat(multicursor): MC HAMMER #41587Justin M. Keyes2026-09-01
| | | | | | | | | | | | | | | | | | | | | Other (squashed) commits: fix(tui): emit ui_send output atomically with the frame Problem: tui_ui_send() writes directly to the TTY, bypassing the output buffer. Sequences sent via nvim_ui_send() (e.g. kitty multiple-cursors, or visual-dot-repeat) always arrive in a separate TTY write from the frame they were computed for. This manifests as "tearing", or e.g. in the case of multicursor the terminal renders text with stale cursor overlays. Solution: - tui_ui_send(): while a frame is being assembled (pending invalid regions or buffered output), buffer instead of writing directly. - Out-of-frame sends (tty queries, clear-on-disable) still write immediately. - mcursor.lua: emit the terminal-cursor update at the end of the redraw cycle (`on_end`, when screen positions are final) instead of vim.schedule().
* fix(cmdwin): allow a user to switch to other buffers #41199Rob Pilling2026-08-28
|
* docs: misc, cwd, vimscript.txt #41356Justin M. Keyes2026-08-17
| | | Extract vimscript.txt from repeat.txt
* feat(input)!: CmdAtom event #41297Justin M. Keyes2026-08-14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: There is no unified notion of a "user action". Vim processes input by one-char-at-a-time, and mostly throws away any hints it might gather about the user's action, with one exception: it stores the last _edit_ action (the "redo buffer", encoded as unstructured `["x][v][count]body` bytes). Plugins can only observe individual keys (vim.on_key) and high-level effects (TextChanged, CursorMoved). Solution: - Users can subscribe to `CmdAtom` events to handle any user action. - Event is deferred; handlers cannot cancel or interfere with user actions. - Capture `CmdSpec` from the normal/insert/visual subsystems. - typeahead/readahead stay unstructured (`buffheader_T`): they are key streams, not commands. - the redo/record buffers become `StringBuilder`: fewer allocations/copies. - Repurpose the input/redo engine to accept `CmdSpec` objects. "atom": one repeatable unit of user input, as a resolved (post-mapping) keysequence plus structured fields. Only user actions, not `:normal`, API calls, or non-"t" `feedkeys`. BREAKING: dot-repeat of an Insert session, replays the entire session including cursor-moves (:help ins-repeat). BREAKING: dot-repeat of a Visual operation, replays the selection instead of operating on a fixed-size region.
* 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.
* refactor(options): drop OptVal, use ObjectJustin M. Keyes2026-07-29
| | | | | | | | | | | | | Problem: The object subsystem has an intermediate representation for no real reason. Besides the code cost, this also adds an extra (api <=> OptVal) conversion step, which is a (small) perf cost. Solution: We already have `Object`, so use it instead. - drop `OptVal`, `OptValData`, `OptValType`, and related boilerplate. - add `kObjectTypeUnset`.
* fix(api): add `lhs` option for keymap deletionBarrett Ruth2026-07-25
|
* docs: misc #40847Justin M. Keyes2026-07-25
| | | | Co-authored-by: Barrett Ruth <br@barrettruth.com> Co-authored-by: Nathan Zeng <nathan.j.zeng@gmail.com>
* feat(eval): declare more "fast" functions #40834Justin M. Keyes2026-07-19
|
* docs: misc, remove some old help tags #40214Justin M. Keyes2026-07-18
| | | | | | | | | | - Remove old help tags: they add noise to cmdline completion. Co-authored-by: acehinnnqru <acehinnnqru@gmail.com> Co-authored-by: KangaZero <samuelyongw@gmail.com> Co-authored-by: Simone Ragusa <hi@interrato.dev> Co-authored-by: Chinmay Dalal <~chinmay/public-inbox@lists.sr.ht> Co-authored-by: coyaSONG <66289470+coyaSONG@users.noreply.github.com> Co-authored-by: Olivia Kinnear <git@superatomic.dev>
* refactor(globals): group Visual-mode globals in VisualState #40777Justin M. Keyes2026-07-16
|
* refactor(api): omit optional paramJustin M. Keyes2026-07-13
|
* fix(path): normalize separators (slashes) #39155tao2026-07-12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Continue separators normalization, and try to keep it at the nvim <-> external boundary, e.g., `fn.xxx`, `api.xxx`, `:xxx` Solution: some key changes - normalize `$HOME-windows` - normalize entry points of changing directory - `nvim_set_current_dir()`, `chdir()` - normalize the named pipe - `--listen` arg, `--server` arg, `:restart` - `serverstart()`, `sockconnect()`, `serverstop()` - make `expand()` respect 'shellslash' again - clean up `did_set_shellslash` - replace `forward_slash` with `TO_SLASH` - remove obsolete `TMP_PATHSEPSTR` - remove `slash_adjust` in `do_autocmd_dirchanged`? - make `fnamemodify()` always return `/` (except when substituting separators via `:s`, `:gs` ?) Note: - these funcs still apply `slash_adjust` on return, as before: `:pwd`, `chdir()`, `exepath()`, `getcwd()` - these funcs alwarys return `/`, unlike before the normalization PRs - `getcompletion()`, `finddir()`, `findfile()` Also - clean up code, comments, formatting and tests - move `TO_SLASH` from `f_chdir` to `changedir_func` - move `TO_SLASH` from `f_bufadd` to `buflist_new` Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* refactor(input): rename getchar.c => input.c #40698Justin M. Keyes2026-07-12
| | | | | | | | | | | | Problem: `getchar.c` is a quirky name and doesn't align with our existing `os/input.c` and `tui/input.c` modules, which encompass the same topic at different layers. Solution: Rename `getchar.c` => `input.c` for discoverability. Introduce `dialog.c` for functionality related to showing confirm prompts, dialogs, etc.
* refactor(ctx): drop aucmd_prepbuf/aucmd_restbuf #40692Justin M. Keyes2026-07-11
|
* refactor: unify context-switching conceptsJustin M. Keyes2026-07-10
|
* 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).
* docs: miscJustin M. Keyes2026-06-11
|
* refactor: make nvim_put() trigger TextPut* with '_' as regnamezeertzjq2026-05-13
|
* fix(messages): fast context for for nvim_echo({kind}) callback #39755luukvbaal2026-05-12
| | | | | | | | Problem: vim.ui_attach() callback for nvim_echo() call that spoofs an internal message kind is executed in fast context. Solution: Set msg_show callback |api-fast| context dynamically at external message callsites, and for internal list_cmd", "progress" and "shell*" messages.
* feat(ui_client): "press ENTER" free nvim crash debuggingbfredl2026-05-11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This feature might be a little silly and niche, but it is very useful for _my_ workflow (and open source is about mee) An issue which is never present on high quality RELEASE builds, but might occur on Debug builds is that the Nvim server crashes on some error in your unfinished PR code. If you compile your debug builds with sanitizers enabled, as you should, the ASAN/UBSAN runtime will print some useful info about your mistake to stderr or a log file, such as a stack trace. This can be used to jump to the error in the code. This allows the nvim server to install a signal hander in the ui client, which can load this log file in a good safe version of nvim and parse it using 'errorformat' This is inspired by the "press ENTER" free workflow of ui2 and applies it beyond the lifetime cycle of the nvim instance. example config: ```lua local asan = vim.env.ASAN_OPTIONS if asan ~= nil and string.match(asan, "log_path=/tmp/nvim_asan") then local myname = "/tmp/nvim_asan."..vim.uv.getpid() local args = {"--embed", "-n", "+set efm=%+A%*[^/]%f:%l:%c", "+silent cfile "..myname, "+silent cfirst", "+silent copen"} vim.api.nvim__set_restart_on_crash("nvim", args) end ``` and run your debug nvim like so ASAN_OPTIONS=handle_abort=1,handle_sigill=1,log_path=/tmp/nvim_asan ./build/bin/nvim
* build(docs): lint more quasi-keysets #39654Justin M. Keyes2026-05-07
| | | | | | | | | 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.
* fix(messages): disallow source="nvim" progress msg #39315luukvbaal2026-05-06
| | | | | | | | | Problem: Internal progress messages use the "nvim" source (since ff68fd6b), plugins shouldn't be allowed to set the progress message source to "nvim". The message ID used for internal progress messages is not identifiable as such. Solution: Disallow setting opts->source to "nvim" with nvim_echo(). Refactor msg_progress() and callees to bypass nvim_echo(). Prepend message id for internal progress messages with "nvim.".
* docs: sort quasi-keysetsJustin M. Keyes2026-04-26
|
* feat(api): nvim_echo(percent=nil) means "unknown" progress #39029Peter Cardenas2026-04-24
| | | | | | | Problem: No way to signal "unknown" or "indeterminate" progress percentage. Solution: Treat percent=nil as "indeterminate" percent.
* fix(api): expose fg_indexed/bg_indexed in nvim_get_hl #39210glepnir2026-04-20
| | | | | | | | | Problem: fg_indexed/bg_indexed were dropped from nvim_get_hl output due to a wrong short_keys guard. HL_FG_INDEXED also wasn't cleared in hl_blend_attrs, and HLATTRS_DICT_SIZE was too small. Solution: Remove the short_keys guard, clear HL_FG_INDEXED in hl_blend_attrs, bump HLATTRS_DICT_SIZE to 24, and clarify docs that these flags mean rgb is an approximation of the cterm palette index.
* fix(lsp): limit number of created highlight groups (#39133)Evgeni Chasnovski2026-04-17
| | | | | | | | | | | | | | | | | | | | | | | | * fix(api): allow silencing "Too many highlight groups" error Problem: Using Lua's `vim.api.nvim_set_hl(0, 'New', {...})` can fail if there are too many existing highlight groups. However, this error can not be silenced with `pcall`. Solution: Make it possible to silence in `nvim_set_hl` and `nvim_get_hl_id_by_name`. * fix(lsp): limit number of groups created by `document_color()` Problem: A file can contain many string colors that would be highlighted by an LSP server. If this number crosses 19999 (maximum number of allowed highlight groups), there are general issues with creating other highlight groups, which can break functionality outside of `vim.lsp.document_color`. Solution: Limit number of highlight groups that are created by `vim.lsp.document_color` to 10000 (half of allowed maximum). This is not a 100% solution (since there can exist more than 10000 other highlight groups), but explicitly checking number of groups is slow and 10000 should (hopefully) be enough for most use cases.
* fix(terminal): forward streamed bracketed paste properly (#39152)zeertzjq2026-04-18
|
* refactor(api): rename "window" to "win" (positional parameters) #39083Justin M. Keyes2026-04-15
| | | | | | | continues d0af4cd9094f. This commit renames positional parameters. This is only "cosmetic", but is intended to make it extra clear which name is preferred, since people often copy existing code despite the guidelines in `:help dev-naming`.
* refactor(api): rename buffer to buf (positional parameters) #39013Justin M. Keyes2026-04-15
| | | | | | | | In 3a4a66017b74, 4d3a67cd6201, df8d98173cbc we renamed "buffer" to "buf" in dict parameters and return-values. This commit renames positional parameters. This is only "cosmetic", but is intended to make it extra clear which name is preferred, since people often copy existing code despite the guidelines in `:help dev-naming`.
* docs: lsp, options, api #38980Justin M. Keyes2026-04-14
| | | | | | | | | docs: lsp, options - revert bogus change to `_meta/builtin_types.lua` from 3a4a66017b74 Close #38991 Co-authored-by: David Mejorado <david.mejorado@gmail.com>
* feat(api): rename buffer to buf in retval #38900Justin M. Keyes2026-04-13
| | | | | | In 3a4a66017b74192caaf9af9af172bdc08e0c1608, 4d3a67cd620152d11ab9b5f5bdd973f84cc2d44b we renamed "buffer" to "buf" in dict parameters. This commit also renames such keys in dict return-values.
* feat(api): nvim_set_hl can set "font" #37668glepnir2026-04-12
| | | | | | Problem: Cannot set highlight group fonts via API, only via :highlight command. Solution: Add font parameter in nvim_set_hl().
* Merge #38882 docsJustin M. Keyes2026-04-12
|\
| * docs: miscJustin M. Keyes2026-04-12
| | | | | | | | | | | | | | | | Close #38748 Close #38866 Co-authored-by: Mario Loriedo <mario.loriedo@gmail.com> Co-authored-by: Anakin Childerhose <anakin@childerhose.ca>
* | fix(api): nvim_get_hl drops groups defined with link_global #38492glepnir2026-04-12
|/ | | | | | | | | Problem: hlgroup2dict passes &ns_id to ns_get_hl twice. The first call (link=true) sets *ns_hl = 0 when link_global is set, so the second call and the sg_cleared guard both see ns_id == 0 and bail out. The group is silently dropped from the result. Solution: use a temporary copy of ns_id for each ns_get_hl call so the original value is preserved.
* fix(messages): truncate warning messages only in display (#38901)zeertzjq2026-04-09
| | | | For now, add a private "_truncate" flag to nvim_echo, using a truncation method similar to showmode().
* fix(:restart): formalize restart event #35223Sathya Pramodh2026-03-28
| | | | | | | | | | | | | | | | | | | Problem: The "restart" event has some problems: - all UI clients must implement a somewhat complex set of setups - UI must be on the same machine as the server - only works for the "current" UI - race/edge case: If the user config has errors / waiting for input, are all UIs able to attach while Nvim is waiting for input? Solution: - Perform the restart on the server, not the client. - Pass listen address (instead of CLI args) in the UI event. - Simplifies UI logic: they only need to attach to new address. - Opens the door for more enhancements in the future, such as allowing all UIs to reattach instead of only the "current" UI. Co-authored-by: zeertzjq <zeertzjq@outlook.com> Co-authored-by: Justin M. Keyes <justinkz@gmail.com>
* docs: news #38464Justin M. Keyes2026-03-28
|
* fix(progress): require "source" for progress-message #38514Shadman2026-03-28
| | | | | | | | | | | Problem: - Progress-events are filtered by "source". But "source" is not required by nvim_echo. - Without "++nested" (force=false), nvim_echo in an event-handler does not trigger Progress events. - vim.health does not declare a "source". Solution: - Make source mandatory for progress-messages - Enable ++nested (force=true) by default when firing Progress event. - Set "source" in vim.health module.
* feat(progress): set Progress-event pattern to "source" #38495Shadman2026-03-27
| | | | | | | | | | | | Problem: Currently, there's no way to distinguish progress messages coming from different sources. Nor can Progress event be easily filtered based on source. Solution: - Add "source" field to nvim_echo-opts. - The Progress event pattern is now defined by the "source" field. - Include the "title" as ev.data. - Unrelated change: set force=false to disable nesting.
* feat(api): nvim_set_hl{update:boolean} #37546glepnir2026-03-25
| | | | | | | Problem: nvim_set_hl always replaces all attributes. Solution: Add update field. When true, merge with existing attributes instead of replacing. Unspecified attributes are preserved. If highlight group doesn't exist, falls back to reset mode.
* docs: api, plugins, ui2Justin M. Keyes2026-03-24
|