# zcatui - TUI Library para Zig > **Última actualización**: 2025-12-08 > **Lenguaje**: Zig 0.15.2 > **Inspiración**: [ratatui](https://github.com/ratatui/ratatui) + [crossterm](https://github.com/crossterm-rs/crossterm) (Rust) > **Estado**: v1.3 - Widgets completos + Animaciones + Clipboard + Menus ## 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.3) - 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 (17 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` | | Input (readline-style) | ✅ | `input.zig` | | Popup | ✅ | `popup.zig` | | Modal | ✅ | `popup.zig` | | Menu + MenuBar | ✅ | `menu.zig` | | **Extras** | ✅ Completo | | | Animation system | ✅ | `src/animation.zig` | | Clipboard (OSC 52) | ✅ | `src/clipboard.zig` | ### Examples (10 demos) | Ejemplo | Descripción | Comando | |---------|-------------|---------| | hello | Minimal TUI app | `zig build hello` | | events_demo | Keyboard/mouse events | `zig build events-demo` | | list_demo | Lista navegable | `zig build list-demo` | | table_demo | Tabla con selección | `zig build table-demo` | | dashboard | Demo completo | `zig build dashboard` | | input_demo | Input readline-style | `zig build input-demo` | | animation_demo | Easing functions | `zig build animation-demo` | | clipboard_demo | OSC 52 clipboard | `zig build clipboard-demo` | | menu_demo | MenuBar + Modal | `zig build menu-demo` | ### Tests | Módulo | Tests | |--------|-------| | Widgets (13 originales) | 103 | | Animation | 12 | | Clipboard | 8 | | Popup | 5 | | Menu | 5 | | Events | 29 | | **Total** | **~160+** | --- ## Widgets Nuevos (v1.3) ### Input (readline-style) Input de texto con edición avanzada. ```zig var state = InputState.init(allocator); defer state.deinit(); const input = Input.init() .setBlock(Block.init().title("Name").borders(Borders.all)) .setPlaceholder("Enter your name..."); input.render(area, buf, &state); // Keyboard handling if (state.handleKey(key_event)) { // Key was consumed by input } ``` **Features:** - Cursor movement (←→, Home, End) - Word navigation (Ctrl+←→) - Delete (Backspace, Del, Ctrl+W, Ctrl+U, Ctrl+K) - Kill/yank (Ctrl+K, Ctrl+Y) - History (↑↓) - Unicode support ### Popup Overlay flotante. ```zig const popup = Popup.init() .setSize(40, 10) .setBlock(Block.init().title("Info").borders(Borders.all)) .setDimBackground(true) .center(); popup.render(area, buf); ``` ### Modal Diálogo con botones. ```zig var modal = Modal.init() .setTitle("Confirm") .setMessage(&.{"Are you sure?"}) .setButtons(&.{ .{ .label = "OK" }, .{ .label = "Cancel" }, }); modal.render(area, buf); // Navigation modal.focusNext(); // Tab modal.focusPrev(); // Shift+Tab const selected = modal.getFocusedButton(); ``` **Helpers:** ```zig const confirm = confirmDialog("Title", &.{"Message"}); const alert = alertDialog("Title", &.{"Message"}); const yesno = yesNoCancelDialog("Title", &.{"Message"}); ``` ### Menu + MenuBar Sistema de menús. ```zig const file_menu = Menu.init().setItems(&.{ MenuItem.action("New", 'n').setShortcut("Ctrl+", 'N'), MenuItem.action("Open", 'o'), MenuItem.separator(), MenuItem.action("Exit", 'q'), }); var menu_bar = MenuBar.init().setItems(&.{ MenuBarItem.init("File", file_menu), MenuBarItem.init("Edit", edit_menu), }); menu_bar.render(area, buf); // Navigation menu_bar.selectNext(); // → menu_bar.selectPrev(); // ← menu_bar.openSelected(); // Enter menu_bar.closeMenus(); // Esc // Dropdown if (menu_bar.open_menu) |idx| { const dropdown_area = menu_bar.getDropdownArea(area, idx); var menu = getCurrentMenu(); menu.render(dropdown_area, buf); } ``` **MenuItem types:** - `.action` - Clickable action - `.separator` - Visual separator - `.submenu` - Opens nested menu - `.toggle` - Checkbox option --- ## Sistema de Animaciones ### Easing Functions ```zig const Easing = zcatui.Easing; // Available: Easing.linear Easing.easeIn / easeOut / easeInOut Easing.easeInCubic / easeOutCubic / easeInOutCubic Easing.easeInExpo / easeOutExpo Easing.easeOutBounce Easing.easeOutElastic Easing.easeOutBack ``` ### Animation ```zig var anim = Animation.init(0, 100, 2000) // 0→100 over 2 seconds .setEasing(Easing.easeOutBounce) .setRepeat(-1) // Infinite .setPingPong(true); // Reverse on repeat // In game loop: anim.advance(delta_ms); const value = anim.getValue(); // f64 const percent = anim.getValueU16(); // u16 (0-65535) ``` ### Timer ```zig var timer = Timer.repeating(1000); // 1 second if (timer.advance(delta_ms)) { // Timer triggered! } ``` ### AnimationGroup ```zig var group = AnimationGroup.parallel(&animations); // or var group = AnimationGroup.sequential(&animations); group.advance(delta_ms); if (group.isComplete()) { ... } ``` --- ## Clipboard (OSC 52) ```zig const clipboard = zcatui.clipboard; const writer = term.backend.stdout.deprecatedWriter(); // Copy to system clipboard try clipboard.copy(allocator, writer, "Hello!"); // Copy to X11 primary selection try clipboard.copySmallTo(writer, "Text", .primary); // Copy to both try clipboard.copySmallTo(writer, "Text", .both); // Clear clipboard try clipboard.clear(writer); ``` **Terminal support:** xterm, iTerm2, kitty, alacritty, WezTerm, foot **tmux:** Enable with `set -g set-clipboard on` --- ## Arquitectura ### Diseño: Immediate Mode Rendering ``` ┌─────────────┐ ┌────────┐ ┌──────────┐ │ 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) │ ├── animation.zig # Easing, Animation, Timer │ ├── clipboard.zig # OSC 52 clipboard support │ ├── 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 │ ├── input.zig # Readline-style input │ ├── popup.zig # Popup + Modal │ └── menu.zig # Menu + MenuBar ├── examples/ │ ├── hello.zig │ ├── events_demo.zig │ ├── list_demo.zig │ ├── table_demo.zig │ ├── dashboard.zig │ ├── input_demo.zig │ ├── animation_demo.zig │ ├── clipboard_demo.zig │ └── menu_demo.zig ├── docs/ │ ├── ARCHITECTURE.md │ ├── WIDGETS.md │ └── API.md ├── build.zig └── CLAUDE.md ``` --- ## 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 ```bash # Compilar todo zig build # Tests zig build test # Ejecutar ejemplos zig build hello zig build events-demo zig build list-demo zig build table-demo zig build dashboard zig build input-demo zig build animation-demo zig build clipboard-demo zig build menu-demo ``` --- ## Funcionalidades Pendientes (Roadmap) ### Prioridad Alta - [ ] **Scrollable containers** - Viewport para contenido largo - [ ] **Textarea widget** - Input multilínea con scroll ### Prioridad Media - [ ] **Sistema LEGO panels** - Patrones de simifactu-fyne (isDirty, composites) - [ ] **Context menu** - Menú contextual (right-click) - [ ] **Tooltips** - Información emergente ### Prioridad Baja - [ ] **Hyperlinks OSC 8** - Links clickeables en terminal - [ ] **Image protocol** - Kitty/iTerm2 inline images - [ ] **Notifications OSC 9/777** - Desktop notifications - [ ] **Tree widget** - Árbol expandible/colapsable - [ ] **File picker** - Selección de archivos ### Performance - [ ] Lazy rendering para widgets grandes - [ ] Pooling de memoria para cells - [ ] SIMD para operaciones de buffer masivas ### Documentación - [ ] Tutorial paso a paso - [ ] API reference generada - [ ] Más ejemplos --- ## Estudio: Sistema LEGO Panels (simifactu-fyne) Se realizó un análisis completo del sistema de paneles de simifactu-fyne. Los patrones clave son: ### 1. Autonomous Panel Interface Cada panel se auto-gestiona: conoce su ID, tipo, sabe construir su UI y refrescarse. ### 2. isDirty Pattern Desacopla notificación (O(1)) de actualización (O(n)): - Observer notifica → solo pone flag `isDirty = true` - Refresh loop verifica `isDirty()` - Panel actualiza solo si necesario - Flags granulares: `dirtyData`, `dirtyColors`, `dirtyConfig`, `dirtySorting` ### 3. Composición LEGO Paneles pequeños se combinan en layouts: - HSplit: Dos paneles lado a lado - VSplit/Border: Top/center/bottom - Composites: Paneles que contienen otros paneles ### 4. WindowComposer Orquestador que maneja: - Registro de paneles por posición (left, center, right, top) - Navegación de foco (NextPanel, PreviousPanel) - Broadcasting de eventos ### 5. Callbacks para comunicación ```go listPanel.OnItemSelected = func(item Item) { detailPanel.LoadItem(item) } ``` **Archivos de referencia:** - `/mnt/cello2/arno/re/recode/go/simifactu-fyne/internal/ui/panels_v3/` --- ## 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 normas - `NORMAS_TRABAJO_CONSENSUADAS.md` - Metodología fundamental - `QUICK_REFERENCE.md` - Cheat sheet rápido - `INFRASTRUCTURE/` - Documentación de servidores ### Protocolo de Inicio de Conversación 1. **Leer** `TEAM_STANDARDS/LAST_UPDATE.md` (detectar cambios recientes) 2. **Leer** este archivo `CLAUDE.md` 3. **Verificar** estado del proyecto (`git status`, `zig build`) 4. **Continuar** desde donde se dejó --- ## Control de Versiones ```bash # 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 --- ## Historial de Desarrollo ### 2025-12-08 - v1.3 (Widgets avanzados + Extras) **Widgets nuevos:** - Input: Readline-style con cursor, word nav, kill/yank, history, Unicode - Popup: Overlay flotante con backdrop dimming - Modal: Diálogo con título, mensaje, botones navegables - Menu: Dropdown menu con shortcuts - MenuBar: Barra horizontal con dropdowns **Sistemas nuevos:** - Animation: Easing functions, Animation, AnimationGroup, Timer - Clipboard: OSC 52 copy/paste support **Ejemplos nuevos:** - list_demo.zig, table_demo.zig, dashboard.zig - input_demo.zig, animation_demo.zig - clipboard_demo.zig, menu_demo.zig **Estudio:** - Análisis completo del sistema LEGO panels de simifactu-fyne ### 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 ### 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 ### 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