Manages LSP completion request lifecycle.
Manages the lifecycle of completion requests: deciding when to trigger, sending async requests to the LSP client, handling responses, and debouncing rapid keystrokes.
Trigger Rules
Completion fires in two cases:
- Trigger character (
.,:, etc.) — fires immediately - Identifier typing — fires after a debounce delay when the user has typed 2+ identifier characters since the last non-identifier
Debouncing
Character-triggered completions are instant. Identifier-triggered completions are debounced at 100ms to avoid flooding the server while the user is typing quickly.
Summary
Types
Result of classifying an incoming LSP completion response without parsing.
Completion bridge state tracked in the Editor.
Functions
Classifies an incoming LSP completion response and updates the bridge's pending-ref bookkeeping, without parsing the (potentially huge) item list.
Dismisses any active completion state and cancels pending requests.
Called when the debounce timer fires. Sends completion requests to all LSP servers attached to the buffer.
Returns the text typed since the trigger position (for prefix filtering).
Checks whether the given character should trigger completion and, if so, sends the request (possibly after a debounce delay).
Returns initial completion bridge state.
Types
@type classification() :: {:primary | :merge, {non_neg_integer(), non_neg_integer()}, String.t(), non_neg_integer()} | :ignore
Result of classifying an incoming LSP completion response without parsing.
The heavy parse/sort/filter is deferred to a Task (see
MingaEditor.CompletionHandling); classification only decides whether the
response is the primary one (replaces the menu), a secondary one to merge,
or stale/ignorable. gen lets a late processed result be discarded if a
newer request batch has superseded it (latest-wins).
@type t() :: %{ pending_ref: reference() | nil, pending_refs: MapSet.t(reference()), debounce_timer: reference() | nil, trigger_position: {non_neg_integer(), non_neg_integer()} | nil, gen: non_neg_integer() }
Completion bridge state tracked in the Editor.
Functions
@spec classify_response(t(), reference(), {:ok, term()} | {:error, term()}, pid()) :: {t(), classification()}
Classifies an incoming LSP completion response and updates the bridge's pending-ref bookkeeping, without parsing the (potentially huge) item list.
This is the cheap, on-the-Editor half of completion handling: it matches the
response ref against the bridge's pending refs and decides what the caller
should do, then returns the trigger position, the prefix typed since the
trigger, and the current request generation. The expensive parse/sort/filter
is performed by the caller in a Task (see MingaEditor.CompletionHandling).
Returns {updated_bridge, classification} where classification is one of:
{:primary, trigger_pos, prefix, gen}— the authoritative response for the request batch; the processed result replaces the menu.{:merge, trigger_pos, prefix, gen}— a secondary server's response to merge into the existing menu.:ignore— stale ref, error, or no live request.
Dismisses any active completion state and cancels pending requests.
Called when the debounce timer fires. Sends completion requests to all LSP servers attached to the buffer.
@spec get_typed_since_trigger( pid(), {non_neg_integer(), non_neg_integer()} ) :: String.t()
@spec get_typed_since_trigger( pid(), {non_neg_integer(), non_neg_integer()} ) :: String.t()
Returns the text typed since the trigger position (for prefix filtering).
@spec maybe_trigger(t(), String.t(), pid()) :: {t(), Minga.Editing.Completion.t() | nil}
Checks whether the given character should trigger completion and, if so, sends the request (possibly after a debounce delay).
char is the character just inserted (a single-character string).
Returns {updated_bridge_state, updated_completion} where completion
may be unchanged (if debouncing) or nil (if dismissed).
@spec new() :: t()
Returns initial completion bridge state.