Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

nx

Top-level nx.* functions (those without a sub-namespace).

nx.mode()

nvim_get_mode(): the editor’s current mode, read from the nx._cur_mode snapshot the server refreshes before each Lua entry. blocking is always false — the in-VM Lua bindings only run when the server is between keys, so it is never blocked on input here. (The dedicated RPC method serves remote clients.)

Defined in api.lua.

nx.current_line()

nvim_get_current_line(): the text of the line the cursor is on in the current window/buffer (no trailing newline). Composed from the cursor row and the buffer’s lines — a completion plugin reads this when it builds a completion context, which runs as soon as its core spins up, so a missing builtin would break completion (and every completion source) at load.

Defined in api.lua.

nx.regex(pattern, opts)

nx.regex(pattern, opts) -> regex: compile pattern into a reusable regex object for matching Lua strings — a more capable string.find/match/gmatch/gsub with a real regex dialect (named groups, alternation, lazy quantifiers, …). The match runs in Rust, so a string you already hold in Lua is matched in place (no copy). For searching buffer text instead, use nx.buf.search. Raises on an invalid pattern.

opts (all optional): engine = “pcre” | “vim” – regex dialect (default “pcre”, the regex crate) plain = false – match the pattern literally (ignores engine) ignorecase = false – case-insensitive match

Offsets follow the string library: 1-based and byte-based, with :find’s end inclusive, so s:sub(re:find(s)) is the matched text. The returned object has:

re:find(s, init?) -> start, end, cap1, … | nil (like string.find) re:match(s, init?) -> the capture(s), or the whole match if the pattern has none, or nil (like string.match) re:gmatch(s) -> iterator over each match’s captures (or whole match) (like string.gmatch) re:gsub(s, repl, n?) -> newstring, count (like string.gsub) repl is a string (%0 whole match, %1-%9 captures, %% literal %), a function called with the captures (return nil/false to keep the match), or a table keyed by the first capture. re:test(s) -> boolean: does the pattern match anywhere

init is 1-based and may be negative to count from the end, as in string.find.

local re = nx.regex([[(\w+)@(\w+)]]) local _, _, user, host = re:find(“to jo@acme now”) – “jo”, “acme” for word in nx.regex([[\w+]]):gmatch(“one two”) do … end local masked = nx.regex([[\d]]):gsub(“id 42”, “*”) – “id **”

Defined in api.lua.

nx.replace_termcodes(str, _from_part, _do_lt, _special)

nvim_replace_termcodes(str, from_part, do_lt, special): in neovim, translate key notation (<CR>, <C-w>, <lt>, …) into the internal terminal-byte encoding. nxvim represents keys as that notation throughout — parse_keys and nvim_feedkeys consume notation directly — so the canonical internal form of a key string already IS the notation, and this returns str unchanged. The result round-trips exactly through nvim_feedkeys (which re-parses the notation), which is the contract callers rely on (build a “feed string”, later feed it). The flags (from_part / do_lt / special) only shape neovim’s byte output and are accepted for call-compatibility; <lt> and the special names are handled by parse_keys at feed time, so no pre-translation is needed here.

Defined in api.lua.

nx.mode_str(_expanded)

nx.mode_str([expanded]) [alias vim.fn.mode]: the single-letter mode code (“n”/“i”/“v”/“V”/“R”/“c”). (Distinct from nx.mode(), which returns the nvim_get_mode {mode, blocking} table.) INCOMPLETE: expanded is ignored — the core has a flat Mode (no operator-pending / sub-state), so mode(1)’s multi-char forms (“no”, “niI”, …) don’t exist here; the short code is returned for both.

Defined in api.lua.

nx.err_writeln(msg)

Message writers (aliases nvim_err_writeln / nvim_err_write / nvim_out_write). Error writers route through nx._echo_err, which lands on the message line and in :messages painted red (the core echo_err path); out_write funnels through print like a plain message. nvim_err_writeln/out_write append a newline; the *_write forms don’t (the message line is line-oriented, so both just emit the text).

Defined in api.lua.

nx.err_write(msg)

No documentation comment in the prelude.

Defined in api.lua.

nx.out_write(msg)

No documentation comment in the prelude.

Defined in api.lua.

nx.list_uis()

nx.list_uis() [alias nvim_list_uis]: the attached UIs. nxvim drives one client at a time, so this reports a single UI sized to the editor screen (vim.o.columns/lines), with the fields a layout calculation reads. The ext_* feature flags are all false (nxvim’s redraw protocol carries no external-UI widgets).

Defined in api.lua.

nx.exec(src, output)

nx.exec(src, output) [alias nvim_exec]: run the ex-command(s) in src and, when output is truthy, return the text they produced (see exec_capture).

Defined in autocmd.lua.

nx.component(def)

nx.component(def) -> { mount(opts) } — build a reactive, Vue-shaped UI component for a plugin surface, then :mount() one or more instances of it. The reactive core is surface-agnostic: the same component can drive a focus-taking buffer or a passive float, chosen per def / mount.

def is a table:

  • render(state, inst) — REQUIRED and PURE. Maps the current state to what’s on screen and returns the surface’s output (see Surfaces). The framework re-runs it automatically whenever reactive state changes, coalesced to ONE render per tick. May be async (call nx.await(...) straight inside it).
  • setup(ctx, props) — OPTIONAL; runs ONCE on mount and owns every side effect — it creates reactive state, subscribes to events, binds keys, fetches data — and RETURNS the state value handed to render. Runs only after the surface is ready, so everything on ctx is already valid (no tick-dance). May be async.
  • surface"view" (default) or "float"; or pass backend (a function(opts) -> adapter) to render to a custom surface.

The ctx handed to setup carries the reactivity and lifecycle:

  • ctx.reactive(tbl) — a deep reactive proxy; writing any key (s.x = 1) schedules a re-render. Iterate with ipairs / # (NOT pairs — PUC 5.4 has no __pairs).
  • ctx.computed(getter) — a cached derived value, read as c() or c.value; it re-evaluates only when a reactive input it read last time has changed.
  • ctx.refresh() — force a re-render. ctx.props — the opts.props from mount.
  • ctx.on_close(fn) / ctx.close() — register a teardown hook / close the instance. On the “view” surface ctx also gains: ctx.view, ctx.bufnr(), ctx.winid(), ctx.line(), ctx.set_cursor(n), ctx.bo / ctx.wo (the view’s buffer/window-local option tables), and ctx.keymap_set(mode, lhs, rhs, opts) (buffer-scoped + nowait by default).

Surfaces — what render returns, and how the surface behaves:

  • “view” — a focus-taking, navigable nx.view buffer (dock / split / grabbing float): the file-tree / list / modal-dialog case. render returns { lines, decor } (or a bare line list). nx.view.component(def) is the sugar.
  • “float” — a NON-focus nx.ui.float content float (the which-key surface): never steals focus, binds no keys. render returns { lines, title?, relative?, border? }; an EMPTY render HIDES the float (a later non-empty one re-opens it), so a component shows/hides purely by what it returns. Only one float component may display at once (a second fails loud rather than clobbering the single content-float slot).

mount(opts) instantiates and returns the instance (with :close()). opts.props is passed to setup; the rest configures the surface — view: name / filetype / dock / split / float (and eob to keep end-of-buffer tildes); float: title / relative / border. Render errors and setup errors are caught and surfaced via nx.notify rather than crashing the editor.

Persistence (view surface) — mount{ persist = "<id>", … } opts a view component into cross-session restore, the high-level form of nx.view.create{ persist=} + nx.view.on_restore. The framework resolves the owning namespace ONCE (from the mount call site, or opts.namespace for a no-attribution context — the same escape-hatch contract as nx.shada.plugin()), records only (namespace, id) + the view’s slot in the session, and on a restart picks fresh-vs-restore for you: it adopts the reserved slot if the session reopened the view, else mounts fresh — no on_restore handler, no VimEnter fallback. The content is the component’s own: setup reads it from ctx.store and a mutation saves it back. A persistent component’s ctx gains:

  • ctx.storenx.shada.plugin(ns) for the resolved owner namespace: an isolated, cross-session key/value slice. Read saved state in setup, write it on every change.
  • ctx.namespace — the resolved owner namespace; ctx.persist_id — the stable id. (examples/view-persist/ is a runnable pinned-notes plugin built on exactly this.)

Example — a live-updating counter in a floating view:

local Counter = nx.component({
  setup = function(ctx)
    local s = ctx.reactive({ n = 0 })
    ctx.keymap_set("n", "+", function() s.n = s.n + 1 end)  -- write -> re-render
    ctx.keymap_set("n", "q", ctx.close)
    return s
  end,
  render = function(s)
    return { lines = { "count: " .. s.n, "", "+ to increment · q to quit" } }
  end,
})
Counter.mount({ float = { width = 30, height = 4, grab = true } })

Defined in component.lua.

nx.on_key_pending(fn)

No documentation comment in the prelude.

Defined in keymap.lua.

nx.on(event, opts, fn)

Events — structured autocmd subscriptions. nx.on(event, opts, fn): the canonical verb. fn (when given) is the handler; otherwise opts.callback / opts.command apply, exactly as the underlying registry expects. Returns the subscription id (droppable with nx.off).

Defined in nx.lua.

nx.off(id)

Drop a subscription created by nx.on.

Defined in nx.lua.

nx.command(name, fn, opts)

User commands — nx.command(name, fn, opts) defines :Name; fn is a function or an ex-command string.

Defined in nx.lua.

nx.uuid()

nx.uuid() -> a fresh random (version-4) UUID as a canonical 8-4-4-4-12 lowercase-hex string, e.g. “f47ac10b-58cc-4372-a567-0e02b2c3d479”. Bytes come from the OS CSPRNG, so each call is unique; handy for a session id, a temp-file name, or any unique key. Available on every build (native and browser/wasm).

Defined in nx.lua.

nx.echo(msg)

nx.echo(msg) -> nil. Append msg (a string) to the message line — the programmatic echo, the canonical form of vim.api.nvim_echo. For a transient, separately-styled notification prefer nx.notify.

Defined in nx.lua.

nx.argv()

nx.argv() -> the list of positional file arguments this process was launched with (strings; empty when none). A launcher / wrapper reads them to forward to a relaunched editor; carried through the NXVIM_ARGV environment variable, so the binary stays the single source of truth.

Defined in nx.lua.

nx.reexec(args)

nx.reexec(args) -> does not return on success. Replace THIS process with a fresh nxvim <args…> of the current executable — a launcher relaunches the editor with chosen flags this way (e.g. { “–shada-namespace”, ns, “–restore-session” }). On Unix this execv()s (never returns on success); elsewhere it spawns and exits with the child’s status. Raises if the exec / spawn itself fails.

Defined in nx.lua.

nx.now_ms()

nx.now_ms() -> a monotonic timestamp in milliseconds (a number) for timing and scheduling math. Unlike os.clock (CPU time, ≈0 across an awaited tick) it advances with real wall-clock time, so it measures durations that span async work.

Defined in nx.lua.

nx.runtime_file(name, all)

nx.runtime_file(name[, all]) -> full paths of runtimepath files matching name (a runtimepath-relative path whose final component may be globbed with *), as a list. With all falsey it returns just the first match (a one- or zero-element list). Reads the LIVE runtimepath, so a plugin installed mid-session contributes its files immediately. The lsp/<server>.lua config-discovery primitive.

Defined in nx.lua.

nx.open(path, opts)

nx.open(path[, opts]) -> nil. Open a file or directory in the editing area, like :edit. With opts.where == "main" it first crosses to the main editor layer (so an open fired from a dock / sidebar keymap lands in the main area, not the dock); the default opens in the current window.

Defined in nx.lua.

nx.run(spec)

nx.run { cmd, args, cwd, env, stdin } -> promise of { code, stdout, stderr }. Runs a child to completion off the input tick, collecting all of stdout. It RESOLVES (never rejects) with the exit result: a non-zero code is the caller’s to act on, and a spawn failure (e.g. binary not found) surfaces as code = -1 with empty output — exactly like vim.system. The one-shot promise twin of nx.run_stream.

Defined in process.lua.

nx.run_stream(spec)

nx.run_stream { cmd, args, cwd, env } -> Stream. Spawns a child and streams its stdout in newline-delimited batches. The streaming twin of nx.run; the picker / completion sources consume it to feed results as they arrive.

Defined in process.lua.

nx.await_each(stream)

nx.await_each(stream): a for-loop iterator over a Stream’s batches. Each step awaits the next batch; the loop ends when the stream is exhausted (:next() resolves nil). MUST run inside an nx.async function (nx.await suspends the enclosing coroutine).

for batch in nx.await_each(stream) do for _, line in ipairs(batch) do … end end

Defined in process.lua.

nx.async(fn)

nx.async(fn) returns a function that, when called, runs fn as a coroutine and returns a promise for its result. Inside, nx.await(p) suspends until p settles and evaluates to its value (or re-raises its rejection as a Lua error), so a sequence of awaits reads top-to-bottom with no nesting:

local load = nx.async(function(path)
  local stat = nx.await(fs.stat(path))
  local data = nx.await(fs.read(path))
  return parse(data, stat)
end)
load("init.lua"):next(use):catch(report)

A rejected await raises inside the coroutine, so you can handle it either way: wrap the await in pcall to catch it locally (PUC 5.2+ yields across a pcall boundary, so this works on nxvim’s 5.4 backend), or let it propagate to the coroutine edge (the returned promise rejects, caught by :catch on the result) or attach :catch to the awaited promise itself.

Defined in promise.lua.

nx.await(awaitable)

nx.await(awaitable): suspend the enclosing nx.async coroutine until awaitable settles. Returns the fulfilment value, or raises the rejection reason as an error (which, uncaught, rejects the async function’s promise). Errors loudly if called outside an nx.async coroutine — there is nothing to suspend.

Defined in promise.lua.

nx.schedule(fn)

nx.schedule(fn): defer fn to the end of the current convergence — it runs after the work that scheduled it settles, no longer nested in the caller’s stack frame (the strict improvement over the old inline fn()), but still within the same input tick (not a later wall-clock turn; that is defer_fn). This is exactly what the colorscheme’s “defer to avoid reentrancy” wants.

Defined in runtime.lua.

nx.schedule_wrap(fn)

nx.schedule_wrap [alias vim.schedule_wrap] (fn): return a function that, when called, schedules fn with whatever arguments it was given — a common plugin idiom for “run this callback safely on the loop”. The captured args ride into the deferred call via a closure.

Defined in runtime.lua.

nx.timer(fn, timeout)

nx.timer(fn, timeout): the canonical timer / defer primitive (aliased by vim.defer_fn) — run fn once, timeout ms from now, on the loop — the off-tick deferral configs use for retry patterns. Returns a handle so the caller can :stop() it before it fires.

Defined in runtime.lua.

nx.on_next_tick(fn)

nx.on_next_tick(fn): run fn on the NEXT event-loop tick — the turn after the current one finishes. The cross-tick sibling of nx.schedule: where nx.schedule fires at the end of THIS convergence (a same-tick microtask, so it cannot observe state that only refreshes between ticks — a freshly-mounted window’s id, a mirror the server repopulates each turn), nx.on_next_tick yields the tick entirely and runs on the next one, when those mirrors have been refreshed. A zero-delay one-shot timer is exactly that. Returns the timer handle, so a caller can :stop() it before it fires. (Poll across several ticks by calling it again from within fn.)

Defined in runtime.lua.

nx.notify(msg, level, _opts)

No documentation comment in the prelude.

Defined in runtime.lua.

nx.notify_once(msg, level, opts)

nx.notify_once [alias vim.notify_once]: in neovim this dedups by message; we have no message history to dedup against during a one-shot colorscheme load, so route to notify.

Defined in runtime.lua.

nx.inspect(value)

nx.inspect [alias vim.inspect]: pretty-print a value (tables recursively).

Defined in runtime.lua.

nx.exists(expr)

nx.exists(expr) [alias vim.fn.exists]: does the vim entity named by expr exist? (1 / 0). nxvim answers the forms it can verify and reports 0 for the rest (rather than a fake

  1. so feature-probing stays honest:
  • ‘&opt’ / ‘&l:opt’ / ‘&g:opt’ / ‘+opt’ -> an option nxvim models. A completion plugin gates every window-option write on exists('+'..key), so an unknown option is skipped instead of erroring the float setup.
  • ‘g:’/‘b:’/‘w:’/‘t:’/‘v:’ prefixed name -> that scoped variable is set.
  • ‘:Cmd’ -> a user command nxvim can confirm (2, neovim’s exact-match value); a buffer-local command for the current buffer counts, like at dispatch.
  • everything else (‘*func’, built-in ‘:write’, bare names) -> 0 (can’t confirm).

Defined in state.lua.

nx.set_option(name, value)

nx.set_option / nx.get_option(name[, value]) [aliases nvim_set_option / nvim_get_option]: the global-scope (deprecated) accessors. Route through nx.o, the canonical global-option table that canonicalizes the scope the name implies.

Defined in state.lua.

nx.get_option(name)

No documentation comment in the prelude.

Defined in state.lua.

nx.npcall(fn, ...)

nx.npcall(fn, …) [alias vim.npcall]: pcall that maps failure to nil — select(2, pcall(...)) on success, nil on error. A neovim helper kept for config/plugin convenience (wrap a call that may raise and treat failure as “no value”).

Defined in stdlib.lua.

nx.nonnil(...)

nx.nonnil(…) [alias vim.nonnil]: the first non-nil argument, or nil (verbatim from neovim’s vim/_core/shared.lua; the replacement for the deprecated vim.F.if_nil). A general helper for defaulting an optional value.

Defined in stdlib.lua.

nx.keytrans(s)

nx.keytrans(s) [alias vim.fn.keytrans]: translate the internal form of a key sequence to readable key notation (<C-w>, <Space>, …). nxvim represents keys AS that notation throughout (parse_keys / nvim_feedkeys consume notation directly, and nvim_replace_termcodes returns its input unchanged), so the internal form already IS the notation — this returns s unchanged, the inverse of nvim_replace_termcodes exactly as in vim.

Defined in stdlib.lua.

nx.print(...)

nx.print(…) [alias vim.print]: pretty-print each argument (via nx.inspect) on the message line and return them unchanged, so it can wrap a value inline. Strings print verbatim; tables are inspected.

Defined in stdlib.lua.

nx.iter(src, state, ctrl)

nx.iter(src[, state, ctrl]) [alias vim.iter]: wrap a list-like table OR a Lua iterator triple in a chainable iterator. The triple form is what vim.iter(vim.fs.parents(p)) passes — vim.fs.parents returns (fn, state, start), which Lua spreads as three args here — so the ancestors are drained eagerly into the item list.

Defined in stdlib.lua.

nx.line(expr)

nx.line(expr) [alias vim.fn.line]: a buffer line number. “.” is the cursor line (1-based), “$” the last line (the line count). The window-relative forms (“w0”/“w$”) need the scroll position, which the mirror doesn’t carry yet, so they error loud.

Defined in vimfn.lua.

nx.col(expr)

nx.col(expr) [alias vim.fn.col]: a byte column (1-based). “.” is the cursor column, “$” one past the end of the cursor line (its byte length + 1), matching vim.

Defined in vimfn.lua.

nx.localtime()

nx.localtime() [alias vim.fn.localtime]: the current time in seconds. nxvim sources this from a MONOTONIC clock (the server’s nx._mono_secs, the same base stamped onto undo nodes), not wall-clock unix epoch, so localtime() - node.time elapsed math (e.g. the undotree visualizer’s “N minutes ago”) stays correct and non-negative across NTP steps and manual clock changes. Only differences matter.

Defined in vimfn.lua.

nx.expand(expr)

nx.expand(expr) [alias vim.fn.expand]: the % (current file) forms autocmd callbacks and statuslines use to resolve paths, backed by the current-buffer snapshot. % is the stored name; %:<mods> routes through fnamemodify (so %:t, %:p, %:h, %:r, %:~:., … all work). A non-% expression errors loud. (the override below extends this with cursor keywords / globs, re-binding nx.expand.)

Defined in vimfn.lua.

nx.getmousepos()

nx.getmousepos() [alias vim.fn.getmousepos]: the most recent mouse event’s position as a dict — screenrow/screencol (1-based global screen cell), winid (the window the cell is in, 0 if none), winrow/wincol (1-based, window-relative, gutter included), line/column (1-based buffer line and byte column, 0 off a window’s text), and coladd (always 0 — nxvim has no ‘virtualedit’). Reads the nx._mouse_pos mirror the server pushes from the editor’s last mouse cell, so a mouse mapping (<RightMouse>, <MiddleMouse>, …) can act on the clicked position rather than the cursor.

Defined in vimfn.lua.