12
--- @see |paste|
---
--- @param lines ...
--- @param phase ...
--- @returns false if client should cancel the paste.
STDLIB DESIGN GUIDELINES *dev-lua*
See also |dev-naming|.
- Keep the core Lua modules |lua-stdlib| simple. Avoid elaborate OOP or
pseudo-OOP designs. Plugin authors just want functions to call, not a big,
fancy inheritance hierarchy.
- Avoid requiring or returning special objects in the Nvim stdlib. Plain
tables or values are easier to serialize, easier to construct from literals,
easier to inspect and print, and inherently compatible with all Lua plugins.
(This guideline doesn't apply to opaque, non-data objects like `vim.cmd`.)
- stdlib functions should follow these common patterns:
- Return |lua-result-or-message| (`any|nil,nil|string`) to communicate
failure, or choose from |dev-error-patterns| when appropriate.
- Accept iterable instead of only table.
- Note: in some cases iterable doesn't make sense, e.g. spair() sorts the
input by definition, so there is no reason for it to accept an iterable,
because the input needs to be "reified"; it can't operate on a "stream".
- Return an iterable (generator) instead of table, if possible.
- Mimic the pairs() or ipairs() interface if the function is intended for
use in a |for-in| loop.
*dev-error-patterns*
To communicate failure to a consumer, choose from these patterns (in order of
preference):
1. `retval, errmsg`
- When failure is normal, or when it is practical for the consumer to
continue (fallback) in some other way. See |lua-result-or-message|.
2. optional result, no errormsg
- Special case of 1. When there is only a single case of "doesn't exist"
(e.g. cache lookup, dict lookup).
3. `error("no luck")`
- For invalid state ("must not happen"), when failure is exceptional, or at
a low level where the consumers are unlikely to handle it in a meaningful
way. Advantage is that propagation happens for free and it's harder to
accidentally swallow errors. (E.g. using
`uv_handle/pipe:write()` without checking return values is common.)
4. `on_error` callback
- For async and "visitors" traversing a graph, where many errors may be
collected while work continues.
5. `vim.notify` (sometimes with optional `opts.silent` (async, visitors ^))
- High-level / application-level messages. End-user invokes these directly.
*dev-patterns*
Interface conventions ~
Where possible, these patterns apply to _both_ Lua and the API:
- When accepting a buffer id, etc., 0 means "current buffer", nil means "all
buffers". Likewise for window id, tabpage id, etc.
- Examples: |vim.lsp.codelens.clear()| |vim.diagnostic.enable()|
- Any function signature that accepts a callback (example: |table.foreach()|)
should place it as the LAST parameter (after opts), if possible (or ALWAYS
for "continuation callbacks"—functions called exactly once).
- Improves readability by placing the less "noisy" arguments near the start.
- Consistent with luv.
- Useful for future async lib which transforms functions of the form
`function(<args>, cb(<ret)>))` => `function(<args>) -> <ret>`.
- Example: >lua
-- ✅ OK:
filter(…, opts, function() … end)
-- ❌ NO:
filter(function() … end, …, opts)
-- ❌ NO:
filter(…, function() … end, opts)
- "Enable" ("toggle") interface and behavior:
- `enable(…, nil)` and `enable(…, {buf=nil})` are synonyms and control the
the "global" enablement of a feature.
- `is_enabled(nil)` and `is_enabled({buf=nil})`, likewise, query the
global state of the feature.
- `enable(…, {buf: number})` sets a buffer-local "enable" flag.
- `is_enabled({buf: number})`, likewise, queries the buffer-local state of
the feature.
- See |vim.lsp.inlay_hint.enable()| and |vim.lsp.inlay_hint.is_enabled()|