Files
fn_registry/cpp/functions/viz/terminal_panel/terminal_panel.md
T
egutierrez 07252c0172 feat(0132): cpp terminal_panel module + ansi_parser
Nuevo modulo reutilizable terminal_panel (fn_term) para ImGui:

Sub-fn ansi_parser_cpp_core (cpp/functions/core/):
- Parser ANSI/VT100 byte-a-byte sin heap allocs por evento
- SGR colores FG/BG 16-color + bold + reset
- Cursor moves CUU/CUD/CUF/CUB + CUP absoluto
- Erase ED(2)/EL(2), CR/LF/BS
- Statemachine 4 estados, thread-unsafe por diseno
- 21 tests unitarios (57 assertions), todos pasan

terminal_panel_cpp_viz (cpp/functions/viz/terminal_panel/):
- terminal_panel.cpp: render ImGui + process_output con list clipper
- terminal_panel_linux.cpp: forkpty + reader thread no-blocking
- terminal_panel_windows.cpp: ConPTY CreatePseudoConsole (SDK >= 17763)
- Scrollback circular configurable (default 5000 lineas)
- Toolbar: clear, copy, reset, scroll-lock + status indicator
- readonly mode: sin input box, send() es no-op
- uses_functions: ansi_parser_cpp_core, logger_cpp_core

Tests:
- test_ansi_parser.cpp: 21 test cases, 57 assertions (PASS)
- test_terminal_panel_smoke.cpp: 3 test cases (PASS: spawn echo hello,
  process exits cleanly, readonly ignores send)

CMake:
- cpp/tests/CMakeLists.txt: add test_ansi_parser + test_terminal_panel_smoke
- primitives_gallery (sub-repo): ver commit separado en apps/primitives_gallery

Pendiente (anti-scope v1):
- Windows ConPTY: stub funcional que compila; join() del reader thread
  via std::thread no implementado (usa CreateThread detached)
- ANSI 256/24-bit color, italics, Unicode wide
- Curses pesados (vim, htop, top) — cursor visible basic solo

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-22 23:35:11 +02:00

4.0 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, tested, tests, test_file_path, file_path, framework, params, output, notes
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports tested tests test_file_path file_path framework params output notes
terminal_panel component cpp viz 1.0.0 impure void fn_term::open(fn_term::TerminalPanel& panel); void fn_term::render(fn_term::TerminalPanel& panel); void fn_term::send(fn_term::TerminalPanel& panel, const std::string& text); void fn_term::close(fn_term::TerminalPanel& panel); Emulador TTY embebible en ImGui. Arranca un proceso hijo via PTY (Linux: forkpty) o ConPTY (Windows 10 v1809+), renderiza el scrollback con colores ANSI 16-color, toolbar (clear/copy/reset/scroll-lock) e input box. Scrollback circular configurable. Soporte readonly para tail-only.
terminal
pty
conpty
imgui
viz
ansi
shell
cpp-dashboard-viz
ansi_parser_cpp_core
logger_cpp_core
false error_go_core
atomic
functional
mutex
string
thread
vector
true
smoke: spawn echo hello and exit, scrollback contains hello
cpp/tests/test_terminal_panel_smoke.cpp cpp/functions/viz/terminal_panel/terminal_panel.cpp imgui
name desc
panel Struct TerminalPanel con config (shell, cwd, env, scrollback_lines, readonly) y estado interno gestionado por open/close/render
render() dibuja toolbar + scrollback con colores ANSI + input box en el area ImGui disponible. open() arranca el proceso hijo y el reader thread. send() escribe texto al stdin del hijo. close() mata el proceso y libera recursos. Linux: requiere -lutil (libutil) para forkpty. Windows: requiere Windows SDK >= 17763 (v1809) para ConPTY. Si el SDK es anterior, open() loguea error y deja is_open()==false. Anti-scope v1: sin tabs multiples, sin SSH, sin curses pesados (vim/htop).

terminal_panel

Emulador TTY embebible en ImGui. Util para: tail de logs en una app de monitoring, ejecutar comandos shell desde un panel de kanban, ver output de compilaciones, consola de debug de agentes.

Ejemplo

#include "viz/terminal_panel/terminal_panel.h"

static fn_term::TerminalPanel s_term;

void render_panel() {
    // Abrir al primer frame.
    if (!s_term.is_open()) {
        s_term.shell = "/bin/bash";
        s_term.scrollback_lines = 2000;
        fn_term::open(s_term);
    }
    fn_term::render(s_term);
}

// Tail readonly de un log:
static fn_term::TerminalPanel s_log_tail;

void render_log_tail() {
    if (!s_log_tail.is_open()) {
        s_log_tail.shell    = "/bin/bash";
        s_log_tail.readonly = true;
        fn_term::open(s_log_tail);
        fn_term::send(s_log_tail, "tail -f /tmp/agent.log\n");
    }
    fn_term::render(s_log_tail);
}

Cuando usarla

Cuando necesitas ver output crudo de un proceso (shell, compilacion, curl, tail) sin salir de la app ImGui. Alternativa a abrir un terminal externo. Especialmente util en apps de monitoring (services_monitor, agents_dashboard) y kanban panels de build.

Gotchas

  • Linux: el CMakeLists del consumidor debe linkar -lutil (o target_link_libraries(... util)) para resolver forkpty.
  • Windows: requiere Windows 10 v1809+ (SDK >= 17763). Si el SDK es anterior, open() deja el panel cerrado y loguea error — no hay panic ni crash.
  • Anti-scope v1: sin soporte de curses pesados (vim, htop, top). El parser ANSI maneja SGR color + cursor básico; programas que usen el modo altscreen o muchas secuencias de cursor se verán mal.
  • Scrollback circular: cuando lines.size() > scrollback_lines, se elimina la primera fila. Esto puede causar saltos visuales si el contenido se está acumulando muy rápido (ej. yes "x"). En v1 el target es 60fps con scrollback de 5000 líneas.
  • Thread safety: render() toma el buf_mutex por el tiempo del render de cada frame. El reader thread también lo toma al actualizar el buffer. En condiciones normales no hay contención significativa.
  • readonly: si true, no se renderiza el input box y send() es no-op. Útil para tail -f o procesos que no necesitan stdin.