Eventos de teclado: - Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind - Soporte para todas las teclas: caracteres, F1-F12, navegación, control - Modificadores: Ctrl, Alt, Shift, Super Eventos de ratón: - MouseEvent, MouseEventKind, MouseButton - Click, release, drag, scroll (up/down/left/right) - Posición (column, row) con modificadores - Protocolos: SGR extended y X10 legacy Parser de escape sequences: - CSI sequences (arrows, F-keys, navigation) - SS3 sequences (F1-F4 alternativo) - SGR mouse protocol (mejores coordenadas) - X10 mouse protocol (compatibilidad) - Focus events, bracketed paste Cursor control: - Visibility: show/hide - Blinking: enable/disable - Styles: block, underline, bar (blinking/steady) - Position: moveTo, moveUp/Down/Left/Right - Save/restore position Terminal integrado: - pollEvent(timeout_ms) - polling con timeout - readEvent() - blocking read - enableMouseCapture/disableMouseCapture - enableFocusChange/disableFocusChange - enableBracketedPaste/disableBracketedPaste Ejemplo interactivo: - examples/events_demo.zig Tests: 47 (29 nuevos para eventos y cursor) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
15 KiB
zcatui - TUI Library para Zig
Última actualización: 2025-12-08 Lenguaje: Zig 0.15.2 Inspiración: ratatui + crossterm (Rust) Estado: v1.2 - Renderizado + Eventos integrados
Descripción del Proyecto
zcatui es una librería para crear interfaces de usuario en terminal (TUI) en Zig puro, combinando las capacidades de ratatui (renderizado) y crossterm (eventos) de Rust.
Objetivo: Proveer una API idiomática Zig para construir aplicaciones TUI interactivas con widgets, layouts, estilos, y manejo de eventos de teclado/ratón, manteniendo la filosofía de Zig: simple, explícito, y sin magia.
Nombre: "zcat" + "ui" (un guiño a ratatui y la mascota de Zig)
Diferencia con Rust: En Rust, ratatui y crossterm son librerías separadas. En zcatui, todo está integrado en una sola librería.
Estado Actual del Proyecto
Implementación Completa (v1.2) - 2025-12-08
| Componente | Estado | Archivo |
|---|---|---|
| Core | ✅ Completo | |
| Style + Color | ✅ | src/style.zig |
| Buffer + Cell | ✅ | src/buffer.zig |
| Text + Span + Line | ✅ | src/text.zig |
| Layout + Constraint | ✅ | src/layout.zig |
| Terminal | ✅ | src/terminal.zig |
| Backend ANSI | ✅ | src/backend/ |
| Eventos (crossterm-style) | ✅ Completo | |
| Event, KeyEvent, MouseEvent | ✅ | src/event.zig |
| EventReader + polling | ✅ | src/event/reader.zig |
| Escape sequence parser | ✅ | src/event/parse.zig |
| Cursor control | ✅ | src/cursor.zig |
| Symbols | ✅ Completo | src/symbols/ |
| Line drawing | ✅ | line.zig |
| Border sets | ✅ | border.zig |
| Block chars | ✅ | block.zig |
| Bar chars | ✅ | bar.zig |
| Braille patterns | ✅ | braille.zig |
| Half-block | ✅ | half_block.zig |
| Scrollbar symbols | ✅ | scrollbar.zig |
| Markers | ✅ | marker.zig |
| Widgets | ✅ Completo (13 widgets) | src/widgets/ |
| Block | ✅ | block.zig |
| Paragraph | ✅ | paragraph.zig |
| List | ✅ | list.zig |
| Table | ✅ | table.zig |
| Gauge + LineGauge | ✅ | gauge.zig |
| Tabs | ✅ | tabs.zig |
| Sparkline | ✅ | sparkline.zig |
| Scrollbar | ✅ | scrollbar.zig |
| BarChart | ✅ | barchart.zig |
| Canvas | ✅ | canvas.zig |
| Chart | ✅ | chart.zig |
| Calendar (Monthly) | ✅ | calendar.zig |
| Clear | ✅ | clear.zig |
Tests
| Archivo | Tests |
|---|---|
| barchart.zig | 16 |
| table.zig | 14 |
| calendar.zig | 10 |
| canvas.zig | 10 |
| list.zig | 10 |
| tabs.zig | 9 |
| chart.zig | 8 |
| gauge.zig | 8 |
| sparkline.zig | 6 |
| scrollbar.zig | 5 |
| block.zig | 3 |
| paragraph.zig | 2 |
| clear.zig | 2 |
| Total widgets | 103 |
Arquitectura
Diseño: Immediate Mode Rendering
Como ratatui, usamos renderizado inmediato con buffers intermedios:
┌─────────────┐ ┌────────┐ ┌──────────┐
│ Application │───▶│ Buffer │───▶│ Terminal │
│ (widgets) │ │ (cells)│ │ (output) │
└─────────────┘ └────────┘ └──────────┘
- Cada frame, la aplicación renderiza TODOS los widgets al buffer
- El buffer se compara con el anterior (diff)
- Solo se envían cambios a la terminal (eficiencia)
Estructura de Archivos
zcatui/
├── src/
│ ├── root.zig # Entry point, re-exports públicos
│ ├── terminal.zig # Terminal + eventos integrados
│ ├── buffer.zig # Buffer + Cell + Rect
│ ├── layout.zig # Layout, Constraint, Direction
│ ├── style.zig # Color, Style, Modifier
│ ├── text.zig # Text, Line, Span, Alignment
│ ├── event.zig # Event, KeyEvent, MouseEvent, KeyCode
│ ├── cursor.zig # Cursor control (shapes, position)
│ ├── event/
│ │ ├── reader.zig # EventReader + polling
│ │ └── parse.zig # Escape sequence parser
│ ├── backend/
│ │ └── backend.zig # ANSI escape sequences backend
│ ├── symbols/
│ │ ├── symbols.zig # Re-exports
│ │ ├── line.zig # Line drawing characters
│ │ ├── border.zig # Border sets
│ │ ├── block.zig # Block elements
│ │ ├── bar.zig # Bar characters
│ │ ├── braille.zig # Braille patterns (256)
│ │ ├── half_block.zig # Half-block chars
│ │ ├── scrollbar.zig # Scrollbar symbols
│ │ └── marker.zig # Chart markers
│ └── widgets/
│ ├── block.zig # Block (borders, titles, padding)
│ ├── paragraph.zig # Text with wrapping
│ ├── list.zig # Selectable list with state
│ ├── table.zig # Multi-column table
│ ├── gauge.zig # Progress bars (Gauge + LineGauge)
│ ├── tabs.zig # Tab navigation
│ ├── sparkline.zig # Mini line graphs
│ ├── scrollbar.zig # Scroll indicator
│ ├── barchart.zig # Bar charts with groups
│ ├── canvas.zig # Drawing (braille/half-block)
│ ├── chart.zig # Line/scatter/bar graphs
│ ├── calendar.zig # Monthly calendar
│ └── clear.zig # Clear/reset area
├── examples/
│ ├── hello.zig # Minimal example
│ └── events_demo.zig # Interactive keyboard/mouse demo
├── docs/
│ ├── ARCHITECTURE.md # Arquitectura detallada
│ ├── WIDGETS.md # Documentación de widgets
│ └── API.md # Referencia de API
├── build.zig
└── CLAUDE.md
Widgets Implementados
Block
Contenedor base con bordes y títulos.
const block = Block.init()
.title("Mi Título")
.borders(Borders.all)
.borderStyle(Style.default.fg(Color.blue));
block.render(area, buf);
Paragraph
Texto con word-wrapping y scroll.
const para = Paragraph.init(text)
.setBlock(block)
.setWrap(.{ .trim = true })
.setAlignment(.center);
para.render(area, buf);
List (con ListState)
Lista seleccionable con scroll automático.
var state = ListState.init();
state.select(2);
const list = List.init(items)
.setBlock(block)
.setHighlightStyle(Style.default.bg(Color.yellow));
list.renderStateful(area, buf, &state);
Table (con TableState)
Tabla multi-columna con selección.
var state = TableState.init();
const table = Table.init(rows, widths)
.setHeader(header_row)
.setHighlightStyle(Style.default.bg(Color.blue));
table.renderStateful(area, buf, &state);
Gauge y LineGauge
Barras de progreso.
const gauge = Gauge.init()
.setRatio(0.75)
.setLabel("75%")
.setGaugeStyle(Style.default.fg(Color.green));
gauge.render(area, buf);
Tabs
Navegación por pestañas.
const tabs = Tabs.init(&titles)
.select(1)
.setHighlightStyle(Style.default.fg(Color.yellow));
tabs.render(area, buf);
Sparkline
Mini gráficos de línea.
const spark = Sparkline.init()
.setData(&data)
.setMax(100)
.setStyle(Style.default.fg(Color.cyan));
spark.render(area, buf);
Scrollbar (con ScrollbarState)
Indicador de scroll.
var state = ScrollbarState.init(100).setPosition(25);
const scrollbar = Scrollbar.init(.vertical_right);
scrollbar.render(area, buf, &state);
BarChart
Gráficos de barras con grupos.
const chart = BarChart.init()
.setData(&bar_groups)
.setBarWidth(5)
.setBarGap(1);
chart.render(area, buf);
Canvas
Dibujo libre con diferentes marcadores.
const canvas = Canvas.init()
.setXBounds(0, 100)
.setYBounds(0, 100)
.setMarker(.braille)
.paint(struct {
pub fn draw(ctx: *Painter) void {
ctx.drawLine(0, 0, 100, 100, Color.red);
ctx.drawCircle(50, 50, 25, Color.blue);
}
}.draw);
canvas.render(area, buf);
Chart
Gráficos de línea/scatter/barras con ejes.
const chart = Chart.init(&datasets)
.setXAxis(x_axis)
.setYAxis(y_axis)
.setLegendPosition(.top_right);
chart.render(area, buf);
Calendar (Monthly)
Calendario mensual.
const cal = Monthly.init(Date.init(2024, 12, 1))
.showMonthHeader(Style.default.fg(Color.blue))
.showWeekdaysHeader(Style.default)
.withEvents(events);
cal.render(area, buf);
Clear
Limpia/resetea un área.
Clear.init().render(area, buf);
Stack Técnico
| Componente | Elección |
|---|---|
| Lenguaje | Zig 0.15.2 |
| Zig path | /mnt/cello2/arno/re/recode/zig/zig-0.15.2/zig-x86_64-linux-0.15.2/zig |
| Backend | ANSI escape sequences (portable) |
| Sin dependencias externas | Solo stdlib de Zig |
| Target | Linux primario, cross-platform objetivo |
Comandos
# Compilar
zig build
# Tests
zig build test
# Tests con resumen
zig build test --summary all
Equipo y Metodología
Quiénes Somos
- Usuario: Desarrollador independiente, proyectos comerciales propios
- Claude: Asistente de programación (Claude Code)
Normas de Trabajo Centralizadas
IMPORTANTE: Todas las normas de trabajo están en:
/mnt/cello2/arno/re/recode/TEAM_STANDARDS/
Archivos clave a leer:
LAST_UPDATE.md- LEER PRIMERO - Cambios recientes en normasNORMAS_TRABAJO_CONSENSUADAS.md- Metodología fundamentalQUICK_REFERENCE.md- Cheat sheet rápidoINFRASTRUCTURE/- Documentación de servidores
Protocolo de Inicio de Conversación
- Leer
TEAM_STANDARDS/LAST_UPDATE.md(detectar cambios recientes) - Leer este archivo
CLAUDE.md - Verificar estado del proyecto (
git status,zig build) - Continuar desde donde se dejó
Principios de Desarrollo
Estándares Zig Open Source (#24 de NORMAS)
Este proyecto será público. El código debe ser ejemplar.
| Aspecto | Estándar |
|---|---|
| Claridad | Código autoexplicativo, nombres descriptivos |
| Comentarios | Doc comments (///) en TODAS las funciones públicas |
| Estructura | Organización lógica, separación de responsabilidades |
| Idiomático | snake_case, error handling explícito, sin magia |
Principios Generales
- DRY: Una sola función por tarea
- Fragmentación: <400 líneas core, <200 líneas utils
- Testing progresivo: Compilar y probar cada cambio
- Funcionalidad > Performance: Primero que funcione, luego optimizar
API de Zig 0.15.2 - Cambios Importantes
Ver guía completa:
TEAM_STANDARDS/INFRASTRUCTURE/ZIG_0.15_GUIA.md
Cambios Clave para este Proyecto
| Componente | Zig 0.15 |
|---|---|
| stdout | std.fs.File.stdout().deprecatedWriter() |
| ArrayList | std.array_list.Managed(T).init(alloc) |
| file.reader() | file.deprecatedReader() |
| sleep | std.Thread.sleep() |
Otros Proyectos del Ecosistema
Proyectos Zig
| Proyecto | Descripción | Estado |
|---|---|---|
| service-monitor | Monitor HTTP/TCP con notificaciones | Completado |
| zcatui | TUI library inspirada en ratatui | v1.0 Completo |
Proyectos Go (referencia)
| Proyecto | Descripción |
|---|---|
| simifactu | API facturación electrónica |
| ms-web (mundisofa) | Web e-commerce |
| 0fiS | Aplicación desktop Fyne |
Infraestructura
| Recurso | Ubicación |
|---|---|
| Git server | git.reugenio.com (Forgejo) |
| Servidor | Simba (188.245.244.244) |
| Docs infra | TEAM_STANDARDS/INFRASTRUCTURE/ |
Control de Versiones
# Remote
git remote: git@git.reugenio.com:reugenio/zcatui.git
# Comandos frecuentes
zig build # Compilar
zig build test # Tests
zig build test --summary all # Tests con detalles
Recursos y Referencias
ratatui (Rust) - Referencia de implementación
- Repo: https://github.com/ratatui/ratatui
- Docs: https://docs.rs/ratatui/latest/ratatui/
- Website: https://ratatui.rs/
- Clone local:
/mnt/cello2/arno/re/recode/ratatui-reference/
Zig
- Docs 0.15: https://ziglang.org/documentation/0.15.0/std/
- Guía migración:
TEAM_STANDARDS/INFRASTRUCTURE/ZIG_0.15_GUIA.md
ANSI Escape Codes
- Referencia: https://en.wikipedia.org/wiki/ANSI_escape_code
- Colores: https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
Optimizaciones de Performance (v1.1)
Implementadas
- Symbol compacto: Almacena UTF-8 directamente (4 bytes max), evita conversión en cada render
- Buffer diff: Iterator que solo retorna celdas modificadas, reduce I/O dramáticamente
- Cell.eql(): Comparación eficiente de celdas para el diff
- Buffer.resize(): Redimensiona preservando contenido existente
- writeSymbol(): Escribe UTF-8 directo sin conversión de codepoint
Pendientes (v1.2+)
- Lazy rendering para widgets grandes
- Pooling de memoria para cells
- SIMD para operaciones de buffer masivas
Funcionalidades Adicionales
- Input handling (keyboard events)
- Mouse support
- Clipboard integration
- Animaciones
Documentación
- Ejemplos completos
- Tutorial paso a paso
- API reference generada
Historial de Desarrollo
2025-12-08 - v1.2 (Eventos - crossterm-style)
- Sistema de eventos integrado (teclado + ratón)
- Event, KeyEvent, MouseEvent, KeyCode types
- EventReader con polling y timeout
- Parser de escape sequences (CSI, SS3, SGR mouse, X10 mouse)
- Cursor control (shapes, blinking, save/restore)
- Terminal integrado: pollEvent(), enableMouseCapture(), enableFocusChange()
- Ejemplo interactivo: events_demo.zig
- Tests: 47 tests (29 nuevos para eventos)
2025-12-08 - v1.1 (Performance)
- Symbol: tipo compacto UTF-8 (4 bytes max)
- Buffer.diff(): renderizado diferencial eficiente
- Cell.eql(): comparación optimizada
- Buffer.resize(): redimensionado con preservación
- writeSymbol(): output UTF-8 directo
- Tests: 18 tests (9 nuevos para optimizaciones)
2025-12-08 - v1.0 (Implementación Completa)
- Implementados todos los widgets de ratatui (13 widgets)
- Sistema de símbolos completo (braille, half-block, borders, etc.)
- 103+ tests en widgets
- Documentación completa (ARCHITECTURE.md, WIDGETS.md, API.md)
2025-12-08 - Inicio del Proyecto
- Creación de CLAUDE.md
- Definición de arquitectura
- Estructura inicial del proyecto