# `MingaEditor.CompletionTrigger`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga_editor/completion_trigger.ex#L1)

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:
1. **Trigger character** (`.`, `:`, etc.) — fires immediately
2. **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.

# `t`

```elixir
@type t() :: %{
  pending_ref: reference() | nil,
  pending_refs: MapSet.t(reference()),
  debounce_timer: reference() | nil,
  trigger_position: {non_neg_integer(), non_neg_integer()} | nil
}
```

Completion bridge state tracked in the Editor.

# `dismiss`

```elixir
@spec dismiss(t()) :: t()
```

Dismisses any active completion state and cancels pending requests.

# `flush_debounce`

```elixir
@spec flush_debounce(t(), [pid()], pid()) :: t()
@spec flush_debounce(t(), pid(), pid()) :: t()
```

Called when the debounce timer fires. Sends completion requests to all
LSP servers attached to the buffer.

# `get_typed_since_trigger`

```elixir
@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).

# `handle_response`

```elixir
@spec handle_response(t(), reference(), {:ok, term()} | {:error, term()}, pid()) ::
  {t(),
   Minga.Editing.Completion.t()
   | {:merge, [Minga.Editing.Completion.item()],
      {non_neg_integer(), non_neg_integer()}}
   | nil}
```

Handles an LSP response for a completion request. Returns the new
completion state if the response matches the pending ref, or nil
if it's stale.

# `maybe_trigger`

```elixir
@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).

# `new`

```elixir
@spec new() :: t()
```

Returns initial completion bridge state.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
