---
name: ansi_parser
kind: function
lang: cpp
domain: core
version: "1.0.0"
purity: pure
signature: "class fn_term::AnsiParser { void feed(const char* data, size_t n, const std::function<void(const fn_term::AnsiEvent&)>& cb); void reset(); uint8_t current_fg() const; uint8_t current_bg() const; uint8_t current_bold() const; }"
description: "Parser ANSI/VT100 minimo byte-a-byte sin alloc heap por evento. Soporta SGR colores FG/BG 16-color + bold + reset, cursor moves (CUP/CUU/CUD/CUF/CUB), erase display/line (ED 2, EL 2), CR/LF/BS. Statemachine simple con 4 estados. Emite AnsiEvent via callback."
tags: [ansi, vt100, terminal, parser, pure, state-machine, cpp-dashboard-viz]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [cstddef, cstdint, functional]
tested: true
tests:
  - "SGR reset sets default colors"
  - "SGR fg color 31 sets red"
  - "SGR bg color 44 sets blue background"
  - "SGR bright fg 91 sets bright red"
  - "SGR bold sets bold flag"
  - "cursor CUU moves up N"
  - "cursor CUF moves forward N"
  - "cursor CUP absolute position"
  - "erase display ED 2"
  - "erase line EL 2"
  - "mixed text and SGR sequence"
  - "newline and carriage return"
test_file_path: "cpp/tests/test_ansi_parser.cpp"
file_path: "cpp/functions/core/ansi_parser.cpp"
framework: ""
params:
  - name: data
    desc: "Puntero al buffer de bytes a procesar (output crudo de PTY/ConPTY)"
  - name: n
    desc: "Numero de bytes en data"
  - name: cb
    desc: "Callback invocado por cada evento emitido. Sin alloc — el AnsiEvent vive en el stack del parser"
output: "Sin retorno directo. Eventos emitidos via callback: AnsiEventType::Char (caracter + atributos SGR actuales), CursorMove (relativo), CursorAbsolute (CUP), EraseDisplay, EraseLine, CarriageReturn, Newline, Backspace"
notes: "Usado por terminal_panel_cpp_viz como paso de parseo del output PTY. Anti-scope v1: sin 256/24-bit color, sin italics/underline, sin Unicode wide, sin OSC/DCS. UTF-8 multi-byte se mapea a '?' en v1."
---

# ansi_parser

Parser ANSI/VT100 minimo para el modulo `terminal_panel`. Sin heap allocs por byte procesado — la maquina de estados vive en el objeto y los `AnsiEvent` se emiten por callback en el stack del caller.

## Ejemplo

```cpp
#include "core/ansi_parser.h"

fn_term::AnsiParser parser;
std::string output;

// Procesar output crudo de PTY:
parser.feed(pty_buf, bytes_read, [&](const fn_term::AnsiEvent& ev) {
    if (ev.type == fn_term::AnsiEventType::Char) {
        // ev.cell.ch = codepoint, ev.cell.fg = color index 0-16
        output += static_cast<char>(ev.cell.ch);
    } else if (ev.type == fn_term::AnsiEventType::Newline) {
        output += '\n';
    }
});
```

## Cuando usarla

Cuando procesas output crudo de un PTY (Linux forkpty) o ConPTY (Windows) y necesitas extraer texto + atributos de color para renderizar en ImGui con `PushStyleColor`. Es la capa de parseo de `terminal_panel`.

## Secuencias soportadas (v1)

| Tipo | Secuencia | AnsiEventType |
|------|-----------|---------------|
| Texto ASCII | bytes 0x20-0x7E | Char |
| CR | `\r` (0x0D) | CarriageReturn |
| LF | `\n` (0x0A) | Newline |
| BS | `\x08` | Backspace |
| SGR reset | `ESC[0m` o `ESC[m` | (actualiza estado interno) |
| SGR bold | `ESC[1m` | (actualiza estado interno) |
| SGR FG 16 | `ESC[30-37m`, `ESC[90-97m` | (actualiza estado interno) |
| SGR BG 16 | `ESC[40-47m`, `ESC[100-107m` | (actualiza estado interno) |
| Cursor UP | `ESC[nA` | CursorMove (Up, n) |
| Cursor DOWN | `ESC[nB` | CursorMove (Down, n) |
| Cursor FWD | `ESC[nC` | CursorMove (Forward, n) |
| Cursor BACK | `ESC[nD` | CursorMove (Back, n) |
| CUP | `ESC[r;cH` | CursorAbsolute (0-based) |
| ED(2) | `ESC[2J` | EraseDisplay |
| EL(2) | `ESC[2K` | EraseLine |

## Gotchas

- Anti-scope v1: no 256-color (`ESC[38;5;Nm`), no 24-bit color, no italics/underline, no curses pesados.
- UTF-8 multi-byte: bytes de continuacion 0x80-0xBF ignorados; inicio 0xC0+ emite `?`. Soporte completo en v2.
- No thread-safe: cada instancia debe usarse desde un solo hilo (el reader thread del PTY).
- `kPalette16[16]` es el color "default" (gris claro). El caller decide si usar el color del tema o la paleta fija.
