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

Custom `:logger` handler that routes log messages to the `*Messages*` buffer.

When the TUI is active, the default console handler writes to stderr which
corrupts the terminal display. This module:

1. Replaces the default `:logger_std_h` handler with a file-based one
   (writes to `~/.local/share/minga/minga.log`)
2. Adds a custom handler that forwards messages to the `*Messages*` buffer
   via `Minga.Events` broadcasts
3. Redirects the `:standard_error` IO device to the same log file so that
   raw BEAM warnings (e.g. `IO.warn/2`) don't corrupt the TUI either

## Crash recovery

When the Editor GenServer is down (e.g., mid-restart after a crash), log
messages are buffered in an ETS table owned by the Application supervisor.
The Editor calls `flush_buffer/0` during `init/1` to replay them into
`*Messages*`. The buffer is capped at `@max_buffered` entries to prevent
unbounded growth during crash loops.

## Installation

Called from the Editor's `init/1` after the `*Messages*` buffer is ready:

    Minga.LoggerHandler.install()

The handler stays installed across Editor restarts so that crash reports
are captured in the ETS buffer. `uninstall/0` is called only during
clean application shutdown (`Application.stop/1`).

`install/0` is idempotent: safe to call on every Editor init even
when the handlers are already in place from a previous Editor lifetime.

# `ensure_buffer_table`

```elixir
@spec ensure_buffer_table() :: :ok
```

Creates the ETS buffer table if it doesn't already exist.

Called from `Minga.Application.start/2` so the table is owned by the
supervisor process and survives Editor crashes.

# `flush_buffer`

```elixir
@spec flush_buffer() :: [{String.t(), atom()}]
```

Flush buffered log messages into the Editor.

Called from the Editor's `init/1` after `*Messages*` is ready. Replays all
buffered messages in order, then clears the buffer. Messages that arrived
while the Editor was down (e.g., supervisor crash reports) will appear
in `*Messages*` as if they'd been logged normally.

# `install`

```elixir
@spec install() :: String.t()
```

Install the file handler and stderr redirect for TUI mode.

Idempotent: skips any handler or redirect that is already in place.
Safe to call on every Editor init, including restarts after a crash
where the handlers survived because `terminate/2` no longer tears them down.

Also ensures the `:log_message` broadcast handler is installed (no-op if
the application boot already added it).

Returns the log file path for display in `*Messages*`.

# `install_messages_handler`

```elixir
@spec install_messages_handler() :: :ok
```

Install just the custom `:log_message`-broadcast handler.

Called from `Minga.Application.start/2` and `Minga.Runtime.start/1` so the
broadcast path is live before any editor (or the gateway, or the singleton
`*Messages*` buffer owner) is up. Idempotent.

Unlike `install/0`, this does not replace the default `:logger` handler
and does not redirect stderr — those are TUI-only concerns and stay in
the editor's init path so headless and `mix` invocations keep stdout/stderr
output.

# `uninstall`

```elixir
@spec uninstall() :: :ok
```

Restore the default console handler and original stderr device.

---

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