Files
neovim/runtime/lua/vim/_meta/builtin.lua
Justin M. Keyes 359459dec6 refactor(exmode): Ex-mode as cmdwin + Lua #40991
Problem:
POSIX-compatible Ex-mode requires special-cases all over the codebase to
match various quirks that don't actually matter to users.
- The main utility of *interactive* Ex-mode is its REPL behavior, and
  that can be achieved with `cmdwin`, which also gains extra UX
  benefits.
- The main utility of *non-interactive* `nvim -es` is for shell
  scripting, where Ex-mode quirks are mostly unhelpful (e.g. the
  "Entering Ex mode" message).

Solution:
- Reimplement *interactive* Ex-mode as a "persistent, insert-mode
  cmdwin" in Lua.
  - "nvim -e/-E" is simply an alias to "gQ".
- Reframe *non-interactive* Ex-mode (`nvim -es`) as "script mode".
  - Drop POSIX Ex-mode quirks.

Improvements:
- "nvim -V1 -es" output ends with a final newline!
- "nvim -V1 -es" no longer shows the "Entering Ex mode" msg. (This was
  pointless noise, unwanted for scripting purposes.)
- stdin is no longer typeahead. Scripts (":lua io.read()") can read
  stdin as data.
- Empty line is a no-op: a stray blank line no longer moves the cursor
  (deviates from POSIX ex "+1"), no longer exits 1 at EOF (E501).

Preserved behavior:
- cursor starts at "$"
- mode()=="cv" (for non-interactive)
- multiline commands (:append/:function/heredoc pull continuation lines)
- bare-range print
- :print=>stdout
- -V1=>stderr
- CRLF input
- continue-after-error and exit codes

Dropped (regressed) POSIX behavior (non-interactive):
- Event loop only ticks while/between commands, not while blocked
  waiting for a stdin line.
- ":g/pat/visual...Q"
- input()/getchar()/":s/x/y/c" no longer consume stdin lines as
  answers: Nvim stops at end-of-input, skipping the rest of the script,
  exit 0. Use ":lua io.read()" instead.
  - If users care about this they should use interactive Ex-mode (`gQ`).
- ":@r" stops at end of the register instead of continuing to read
  cmdline input from stdin.
2026-07-27 06:25:21 -04:00

271 lines
10 KiB
Lua

---@meta
-- This file is NOT generated, edit it directly.
-- luacheck: no unused args
error('Cannot require a meta file')
--- @brief <pre>help
--- vim.api.{func}({...}) *vim.api*
--- Invokes Nvim |API| function {func} with arguments {...}.
--- Example: call the "nvim_get_current_line()" API function: >lua
--- print(tostring(vim.api.nvim_get_current_line()))
---
--- vim.NIL *vim.NIL*
--- Special value representing NIL in |RPC| and |v:null| in Vimscript
--- conversion, and similar cases. Lua `nil` cannot be used as part of a Lua
--- table representing a Dictionary or Array, because it is treated as
--- missing: `{"foo", nil}` is the same as `{"foo"}`.
---
--- vim.type_idx *vim.type_idx*
--- Type index for use in |lua-special-tbl|. Specifying one of the values from
--- |vim.types| allows typing the empty table (it is unclear whether empty Lua
--- table represents empty list or empty array) and forcing integral numbers
--- to be |Float|. See |lua-special-tbl| for more details.
---
--- vim.val_idx *vim.val_idx*
--- Value index for tables representing |Float|s. A table representing
--- floating-point value 1.0 looks like this: >lua
--- {
--- [vim.type_idx] = vim.types.float,
--- [vim.val_idx] = 1.0,
--- }
--- < See also |vim.type_idx| and |lua-special-tbl|.
---
--- vim.types *vim.types*
--- Table with possible values for |vim.type_idx|. Contains two sets of
--- key-value pairs: first maps possible values for |vim.type_idx| to
--- human-readable strings, second maps human-readable type names to values
--- for |vim.type_idx|. Currently contains pairs for `float`, `array` and
--- `dictionary` types.
---
--- Note: One must expect that values corresponding to `vim.types.float`,
--- `vim.types.array` and `vim.types.dictionary` fall under only two following
--- assumptions:
--- 1. Value may serve both as a key and as a value in a table. Given the
--- properties of Lua tables this basically means “value is not `nil`”.
--- 2. For each value in `vim.types` table `vim.types[vim.types[value]]` is the
--- same as `value`.
--- No other restrictions are put on types, and it is not guaranteed that
--- values corresponding to `vim.types.float`, `vim.types.array` and
--- `vim.types.dictionary` will not change or that `vim.types` table will only
--- contain values for these three types.
---
--- *log_levels* *vim.log.levels*
--- Log levels are one of the values defined in `vim.log.levels`:
---
--- vim.log.levels.DEBUG
--- vim.log.levels.ERROR
--- vim.log.levels.INFO
--- vim.log.levels.TRACE
--- vim.log.levels.WARN
--- vim.log.levels.OFF
---
--- </pre>
---@nodoc
---@class vim.NIL
---@type vim.NIL
---@nodoc
vim.NIL = ...
--- Returns true if the code is executing as part of a "fast" event handler,
--- where most of the API is disabled. These are low-level events (e.g.
--- |lua-loop-callbacks|) which can be invoked whenever Nvim polls for input.
--- When this is `false` most API functions are callable (but may be subject
--- to other restrictions such as |textlock|).
function vim.in_fast_event() end
--- Creates a special empty table (marked with a metatable), which Nvim
--- converts to an empty dictionary when translating Lua values to Vimscript
--- or API types. Nvim by default converts an empty table `{}` without this
--- metatable to an list/array.
---
--- Note: If numeric keys are present in the table, Nvim ignores the metatable
--- marker and converts the dict to a list/array anyway.
--- @return table
function vim.empty_dict() end
--- Sends {event} to {channel} via |RPC| and returns immediately. If {channel}
--- is 0, the event is broadcast to all channels.
---
--- This function also works in a fast callback |lua-loop-callbacks|.
--- @param channel integer
--- @param method string
--- @param ...? any
function vim.rpcnotify(channel, method, ...) end
--- Invokes |RPC| `method` on `channel` and blocks until a response is received.
---
--- Note: Msgpack NIL values in the response are represented as |vim.NIL|.
---
--- Example: see [nvim_exec_lua()]
---
--- @param channel integer
--- @param method string
--- @param ...? any
function vim.rpcrequest(channel, method, ...) end
--- Compares strings case-insensitively.
--- @param a string
--- @param b string
--- @return 0|1|-1
--- if strings are
--- equal, {a} is greater than {b} or {a} is lesser than {b}, respectively.
function vim.stricmp(a, b) end
--- Gets a list of the starting byte positions of each UTF-8 codepoint in the given string.
---
--- Embedded NUL bytes are treated as terminating the string.
--- @param str string
--- @return integer[]
function vim.str_utf_pos(str) end
--- Gets the distance (in bytes) from the starting byte of the codepoint (character) that {index}
--- points to.
---
--- The result can be added to {index} to get the starting byte of a character.
---
--- Examples:
---
--- ```lua
--- -- The character 'æ' is stored as the bytes '\xc3\xa6' (using UTF-8)
---
--- -- Returns 0 because the index is pointing at the first byte of a character
--- vim.str_utf_start('æ', 1)
---
--- -- Returns -1 because the index is pointing at the second byte of a character
--- vim.str_utf_start('æ', 2)
--- ```
---
--- @param str string
--- @param index integer
--- @return integer
function vim.str_utf_start(str, index) end
--- Gets the distance (in bytes) from the last byte of the codepoint (character) that {index} points
--- to.
---
--- Examples:
---
--- ```lua
--- -- The character 'æ' is stored as the bytes '\xc3\xa6' (using UTF-8)
---
--- -- Returns 0 because the index is pointing at the last byte of a character
--- vim.str_utf_end('æ', 2)
---
--- -- Returns 1 because the index is pointing at the penultimate byte of a character
--- vim.str_utf_end('æ', 1)
--- ```
---
--- @param str string
--- @param index integer
--- @return integer
function vim.str_utf_end(str, index) end
--- The result is a String, which is the text {str} converted from
--- encoding {from} to encoding {to}. When the conversion fails `nil` is
--- returned. When some characters could not be converted they
--- are replaced with "?".
--- The encoding names are whatever the iconv() library function
--- can accept, see ":Man 3 iconv".
---
--- @param str string Text to convert
--- @param from string Encoding of {str}
--- @param to string Target encoding
--- @return string? : Converted string if conversion succeeds, `nil` otherwise.
function vim.iconv(str, from, to, opts) end
--- Schedules {fn} to be invoked soon by the main event-loop. Useful
--- to avoid |textlock| or other temporary restrictions.
--- @param fn fun()
--- @return nil result
--- @return string? err Error message if scheduling failed, `nil` otherwise.
function vim.schedule(fn) end
---@nodoc
---@class vim._core
vim._core = {}
--- @nodoc
--- Polls the main event loop for up to {timeout} milliseconds.
--- @param timeout integer
--- @param fast_only boolean
function vim._core.loop_poll(timeout, fast_only) end
--- @nodoc
--- Flushes pending UI updates.
function vim._core.ui_flush() end
--- @nodoc
--- Checks for interrupt, clears it, and consumes input if present.
--- @return boolean
function vim._core.check_interrupt() end
--- @nodoc
--- Executes one Ex command line obtained from `getline`, which is also called for any
--- continuation lines (`:append` text, `:function` body, heredoc, …). See `vim._core.exmode`.
--- @param getline fun(): string?
--- @return boolean # false if {getline} returned nil before any line was read (EOF).
function vim._core.ex_docmd(getline) end
--- @nodoc
--- Parses `keys` (internal representation) into a list of key chords. See |vim.keycode()|.
--- @param keys string
--- @return vim.keycode.chord[]
function vim._core.keyparse(keys) end
--- Subscribe to |ui-events|, similar to |nvim_ui_attach()| but receive events in a Lua callback.
--- Used to implement screen elements like popupmenu or message handling in Lua.
---
--- {callback} receives event name plus additional parameters. See |ui-popupmenu|
--- and the sections below for event format for respective events.
---
--- Callbacks for `msg_show` events originating from internal messages (as
--- opposed to events from commands or API calls) are executed in |api-fast|
--- context; showing the message needs to be scheduled.
---
--- Excessive errors inside the callback will result in forced detachment.
---
--- WARNING: This api is considered experimental. Usability will vary for
--- different screen elements. In particular `ext_messages` behavior is subject
--- to further changes and usability improvements. This is expected to be
--- used to handle messages when setting 'cmdheight' to zero (which is
--- likewise experimental).
---
--- Example (stub for a |ui-popupmenu| implementation):
---
--- ```lua
--- ns = vim.api.nvim_create_namespace('my_fancy_pum')
---
--- vim.ui_attach(ns, {ext_popupmenu=true}, function(event, ...)
--- if event == 'popupmenu_show' then
--- local items, selected, row, col, grid = ...
--- print('display pum ', #items)
--- elseif event == 'popupmenu_select' then
--- local selected = ...
--- print('selected', selected)
--- elseif event == 'popupmenu_hide' then
--- print('FIN')
--- end
--- end)
--- ```
---
--- @since 0
---
--- @param ns integer Namespace ID
--- @param opts table<string, any> Optional parameters.
--- - {ext_…}? (`boolean`) Any of |ui-ext-options|, if true
--- enable events for the respective UI element.
--- - {set_cmdheight}? (`boolean`) If false, avoid setting
--- 'cmdheight' to 0 when `ext_messages` is enabled.
--- @param callback fun(event: string, ...): any Function called for each UI event.
--- A truthy return value signals to Nvim that the event is handled,
--- in which case it is not propagated to remote UIs.
function vim.ui_attach(ns, opts, callback) end
--- Detach a callback previously attached with |vim.ui_attach()| for the
--- given namespace {ns}.
--- @param ns integer Namespace ID
function vim.ui_detach(ns) end