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

Editor orchestration GenServer.

Ties together the buffer, port manager, viewport, and modal FSM. Receives
input events from the Port Manager, routes them through `Minga.Mode.process/3`,
executes the resulting commands against the buffer, recomputes the visible
region, and sends render commands back to the Zig renderer.

The editor starts in **Normal mode** (Vim-style). The status line reflects
the current mode: `-- NORMAL --`, `-- INSERT --`, etc.

# `effect`

```elixir
@type effect() ::
  :render
  | {:render, delay_ms :: pos_integer()}
  | {:open_file, String.t()}
  | {:switch_buffer, pid()}
  | {:set_status, String.t()}
  | :clear_status
  | {:push_overlay, module()}
  | {:pop_overlay, module()}
  | {:log_message, String.t()}
  | {:log_warning, String.t()}
  | {:log, atom(), atom(), String.t()}
  | :sync_agent_buffer
  | {:update_tab_label, String.t()}
  | {:monitor, pid()}
  | :stop_spinner
  | :start_spinner
  | {:rebuild_agent_session, MingaEditor.State.Tab.t()}
  | {:request_semantic_tokens}
  | {:send_after, term(), non_neg_integer()}
  | {:conceal_spans, pid(), [map()]}
  | {:prettify_symbols, pid()}
  | {:update_agent_styled_cache}
  | {:evict_parser_trees_timer}
  | {:refresh_tool_picker}
  | {:save_session_async, term(), keyword()}
  | {:restart_session_timer}
  | {:cancel_session_timer}
  | {:recover_swap_entries, [Minga.Session.swap_entry()]}
  | {:restore_session, keyword()}
  | {:request_code_lens}
  | {:request_inlay_hints}
  | {:save_session_deferred}
  | {:handle_git_remote_result, reference(), term()}
```

Side effects returned by event handlers and pure state functions.

* `:render` — schedule a debounced render
* `{:render, delay_ms}` — schedule render with custom delay
* `{:open_file, path}` — open a file in a new or existing buffer
* `{:switch_buffer, pid}` — make this buffer active
* `{:set_status, msg}` — show a status message in the minibuffer
* `:clear_status` — clear the status message
* `{:push_overlay, module}` — push an overlay handler onto the focus stack
* `{:pop_overlay, module}` — pop an overlay handler from the focus stack
* `{:log_message, msg}` — log to *Messages* buffer
* `{:log_warning, msg}` — log to both *Messages* and *Warnings* (warning level)
* `{:log, subsystem, level, msg}` — log via Minga.Log
* `:sync_agent_buffer` — sync agent buffer with session output
* `{:update_tab_label, label}` — update active tab label
* `{:monitor, pid}` — monitor a buffer process
* `{:stop_spinner}` — cancel outgoing agent spinner timer
* `{:start_spinner}` — start incoming agent spinner timer
* `{:rebuild_agent_session, tab}` — rebuild agent state from session process
* `{:request_semantic_tokens}` — request semantic tokens from LSP
* `{:send_after, msg, delay}` — schedule a self-send after delay
* `{:conceal_spans, pid, spans}` — apply conceal spans to a buffer
* `{:prettify_symbols, pid}` — run prettify symbols on a buffer
* `{:update_agent_styled_cache}` — re-cache GUI styled messages
* `{:evict_parser_trees_timer}` — schedule next eviction check
* `{:refresh_tool_picker}` — refresh tool picker if open
* `{:save_session_async, snapshot, opts}` — persist session in background
* `{:restart_session_timer}` — restart the periodic session timer
* `{:cancel_session_timer}` — cancel the periodic session timer
* `{:recover_swap_entries, entries}` — recover swap file entries
* `{:restore_session, opts}` — restore session from disk
* `{:request_code_lens}` — request fresh code lenses from LSP
* `{:request_inlay_hints}` — request fresh inlay hints from LSP
* `{:save_session_deferred}` — send :save_session to self
* `{:handle_git_remote_result, ref, result}` — process git remote result

# `start_opt`

```elixir
@type start_opt() ::
  {:name, GenServer.name()}
  | {:port_manager, GenServer.server()}
  | {:buffer, pid()}
  | {:width, pos_integer()}
  | {:height, pos_integer()}
  | {:suppress_tool_prompts, boolean()}
```

Options for starting the editor.

# `state`

```elixir
@type state() :: MingaEditor.State.t()
```

Internal state.

# `apply_effects`

```elixir
@spec apply_effects(MingaEditor.State.t(), [effect()]) :: MingaEditor.State.t()
```

Applies a list of effects to the editor state.

Agent event handlers return `{new_state, [effect()]}` from their callbacks.
The Editor interprets each effect. This keeps handlers testable as
pure `state -> {state, effects}` functions.

# `cast`

```elixir
@spec cast(term(), GenServer.server()) :: :ok
```

Send an async message to the Editor GenServer. Used by background tasks.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `ensure_buffer_for_path`

```elixir
@spec ensure_buffer_for_path(String.t(), GenServer.server()) ::
  {:ok, pid()} | {:error, term()}
```

Ensures a buffer exists for the given file path, opening one if needed.

Delegates to `Buffer.ensure_for_path/1` for the actual buffer start, then
casts to the Editor to register the buffer in the workspace (buffer list,
monitoring, log message). The buffer is added in the background without
switching the active window.

Layer 2 callers that need workspace registration should use this function.
Layer 1 callers (agent tools) should use `Buffer.ensure_for_path/1` directly.

# `log_to_messages`

```elixir
@spec log_to_messages(String.t(), GenServer.server()) :: :ok
```

Log a message to the *Messages* buffer. Used by the custom Logger handler.

# `log_to_warnings`

```elixir
@spec log_to_warnings(String.t(), GenServer.server()) :: :ok
```

Log a warning/error to the *Warnings* buffer with auto-popup.

Used by the custom Logger handler. The popup opens without stealing
focus. Once the user dismisses it with `q`, new warnings are logged
silently until the user explicitly re-opens via `SPC b W`.

# `open_file`

```elixir
@spec open_file(GenServer.server(), String.t()) :: :ok | {:error, term()}
```

Opens a file in the editor.

# `render`

```elixir
@spec render(GenServer.server()) :: :ok
```

Triggers a full re-render of the current state.

# `start_link`

```elixir
@spec start_link([start_opt()]) :: GenServer.on_start()
```

Starts the editor.

---

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