zcatui/CLAUDE.md
reugenio 2a62c0f60b Inicio proyecto zcatui - TUI library para Zig
Librería TUI inspirada en ratatui (Rust), implementada en Zig 0.15.2.

Estructura inicial:
- src/style.zig: Color, Style, Modifier
- src/buffer.zig: Cell, Buffer, Rect
- src/layout.zig: Layout, Constraint, Direction
- src/terminal.zig: Terminal abstraction
- src/backend/backend.zig: ANSI escape sequences
- src/widgets/block.zig: Block con borders y título
- src/widgets/paragraph.zig: Paragraph con wrapping
- examples/hello.zig: Demo funcional

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-08 01:56:44 +01:00

462 lines
13 KiB
Markdown

# zcatui - TUI Library para Zig
> **Última actualización**: 2025-12-08
> **Lenguaje**: Zig 0.15.2
> **Inspiración**: [ratatui](https://github.com/ratatui/ratatui) (Rust TUI library)
## Descripción del Proyecto
**zcatui** es una librería para crear interfaces de usuario en terminal (TUI) en Zig puro, inspirada en ratatui de Rust.
**Objetivo**: Proveer una API idiomática Zig para construir aplicaciones TUI con widgets, layouts, y estilos, 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)
---
## Arquitectura Objetivo
### 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)
### Módulos Principales (Objetivo)
```
zcatui/
├── src/
│ ├── root.zig # Entry point, re-exports públicos
│ ├── terminal.zig # Terminal abstraction
│ ├── buffer.zig # Buffer + Cell types
│ ├── layout.zig # Layout, Constraint, Rect
│ ├── style.zig # Color, Style, Modifier
│ ├── text.zig # Text, Line, Span
│ ├── backend/
│ │ ├── backend.zig # Backend interface
│ │ └── ansi.zig # ANSI escape sequences (default)
│ └── widgets/
│ ├── widget.zig # Widget trait/interface
│ ├── block.zig # Block (borders, titles)
│ ├── paragraph.zig # Text paragraphs
│ ├── list.zig # Selectable lists
│ ├── table.zig # Tables with columns
│ ├── gauge.zig # Progress bars
│ ├── chart.zig # Line/bar charts
│ ├── canvas.zig # Arbitrary drawing
│ └── tabs.zig # Tab navigation
├── build.zig
└── examples/
├── hello.zig # Minimal example
├── demo.zig # Feature showcase
└── counter.zig # Interactive counter
```
---
## Fases de Implementación
### Fase 1: Core (Mínimo Viable)
- [ ] Buffer + Cell (almacenamiento de caracteres + estilos)
- [ ] Style + Color (colores 16, 256, RGB)
- [ ] Rect (área rectangular)
- [ ] Backend ANSI (escape sequences para cualquier terminal)
- [ ] Terminal (init, draw, restore)
- [ ] Widget trait básico
### Fase 2: Layout
- [ ] Constraint (Min, Max, Percentage, Length, Ratio)
- [ ] Layout (horizontal, vertical splitting)
- [ ] Direction (Horizontal, Vertical)
### Fase 3: Widgets Básicos
- [ ] Block (borders, titles, padding)
- [ ] Paragraph (texto con wrapping)
- [ ] List (items seleccionables)
### Fase 4: Widgets Avanzados
- [ ] Table (columnas, headers, selección)
- [ ] Gauge (barra de progreso)
- [ ] Tabs (navegación por pestañas)
- [ ] Chart (gráficos simples)
- [ ] Canvas (dibujo libre con braille/block chars)
### Fase 5: Extras
- [ ] Input handling (keyboard events)
- [ ] Mouse support
- [ ] Scrolling
- [ ] Animations (opcional)
---
## Conceptos Clave de ratatui a Replicar
### 1. Cell
Unidad mínima del buffer: un carácter + su estilo.
```zig
const Cell = struct {
char: u21, // Unicode codepoint
fg: Color, // Foreground color
bg: Color, // Background color
modifiers: Modifiers, // Bold, italic, underline, etc.
};
```
### 2. Buffer
Grid de celdas que representa el estado de la terminal.
```zig
const Buffer = struct {
area: Rect,
cells: []Cell,
pub fn get(self: *Buffer, x: u16, y: u16) *Cell { ... }
pub fn set_string(self: *Buffer, x: u16, y: u16, text: []const u8, style: Style) void { ... }
pub fn diff(self: *Buffer, other: *Buffer) []Update { ... }
};
```
### 3. Rect
Área rectangular en la terminal.
```zig
const Rect = struct {
x: u16,
y: u16,
width: u16,
height: u16,
pub fn inner(self: Rect, margin: Margin) Rect { ... }
pub fn intersection(self: Rect, other: Rect) Rect { ... }
};
```
### 4. Style
Combinación de colores y modificadores.
```zig
const Style = struct {
fg: ?Color = null,
bg: ?Color = null,
modifiers: Modifiers = .{},
pub fn fg(color: Color) Style { ... }
pub fn bg(color: Color) Style { ... }
pub fn bold() Style { ... }
pub fn patch(self: Style, other: Style) Style { ... }
};
```
### 5. Layout
Sistema de distribución de espacio.
```zig
const Layout = struct {
direction: Direction,
constraints: []const Constraint,
pub fn split(self: Layout, area: Rect) []Rect { ... }
};
const Constraint = union(enum) {
length: u16, // Exactly N cells
min: u16, // At least N cells
max: u16, // At most N cells
percentage: u16, // N% of available space
ratio: struct { num: u32, den: u32 },
};
```
### 6. Widget Interface
Trait que deben implementar todos los widgets.
```zig
const Widget = struct {
ptr: *anyopaque,
render_fn: *const fn(*anyopaque, Rect, *Buffer) void,
pub fn render(self: Widget, area: Rect, buf: *Buffer) void {
self.render_fn(self.ptr, area, buf);
}
};
// Ejemplo implementación:
const Block = struct {
title: ?[]const u8 = null,
borders: Borders = .all,
style: Style = .{},
pub fn widget(self: *Block) Widget {
return .{
.ptr = self,
.render_fn = render,
};
}
fn render(ptr: *anyopaque, area: Rect, buf: *Buffer) void {
const self: *Block = @ptrCast(@alignCast(ptr));
// ... render logic
}
};
```
---
## Referencia: ratatui Widgets
| Widget | Descripción | Prioridad |
|--------|-------------|-----------|
| **Block** | Contenedor con bordes y título | Alta |
| **Paragraph** | Texto con wrap y scroll | Alta |
| **List** | Lista seleccionable | Alta |
| **Table** | Tabla con columnas | Media |
| **Gauge** | Barra de progreso | Media |
| **Sparkline** | Gráfico mini de línea | Baja |
| **Chart** | Gráficos de línea/barras | Baja |
| **Canvas** | Dibujo libre (braille) | Baja |
| **BarChart** | Gráfico de barras | Baja |
| **Tabs** | Navegación por tabs | Media |
| **Scrollbar** | Indicador de scroll | Media |
| **Calendar** | Widget de calendario | Baja |
---
## 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 |
---
## 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ó
---
## 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 |
```zig
/// Renderiza un widget Block en el área especificada.
///
/// Dibuja los bordes según `borders` y el título si está definido.
/// El área interior queda disponible para contenido hijo.
pub fn render(self: *Block, area: Rect, buf: *Buffer) void {
// ...
}
```
### 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()` |
### Terminal I/O
```zig
// Escribir a stdout
const stdout = std.fs.File.stdout();
const writer = stdout.deprecatedWriter();
try writer.print("\x1b[2J", .{}); // Clear screen
// Leer de stdin (para eventos)
const stdin = std.fs.File.stdin();
const reader = stdin.deprecatedReader();
```
---
## Otros Proyectos del Ecosistema
### Proyectos Zig
| Proyecto | Descripción | Estado |
|----------|-------------|--------|
| **service-monitor** | Monitor HTTP/TCP con notificaciones | Completado |
### 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
```bash
# Remote (cuando se cree el repo)
git remote: git@git.reugenio.com:reugenio/zcatui.git
# Comandos frecuentes
zig build # Compilar
zig build test # Tests
zig build run -- examples/hello.zig # Ejecutar ejemplo
```
---
## Ejemplo de Uso (Objetivo Final)
```zig
const std = @import("std");
const zcatui = @import("zcatui");
const Terminal = zcatui.Terminal;
const Block = zcatui.widgets.Block;
const Paragraph = zcatui.widgets.Paragraph;
const Layout = zcatui.Layout;
const Constraint = zcatui.Constraint;
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Inicializar terminal
var term = try Terminal.init(allocator);
defer term.deinit();
// Loop principal
while (true) {
try term.draw(struct {
pub fn render(frame: *Frame) void {
// Layout: dividir en 2 áreas
const chunks = Layout.vertical(&.{
Constraint.length(3),
Constraint.min(0),
}).split(frame.area);
// Header
var header = Block.init()
.title("zcatui Demo")
.borders(.all);
frame.render(header.widget(), chunks[0]);
// Content
var content = Paragraph.init("Hello from zcatui!")
.block(Block.init().borders(.all));
frame.render(content.widget(), chunks[1]);
}
}.render);
// Handle input
if (try term.pollEvent()) |event| {
if (event.key == .q) break;
}
}
}
```
---
## Recursos y Referencias
### ratatui (Rust)
- Repo: https://github.com/ratatui/ratatui
- Docs: https://docs.rs/ratatui/latest/ratatui/
- Website: https://ratatui.rs/
### 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
---
## Estado del Proyecto
| Componente | Estado |
|------------|--------|
| CLAUDE.md | ✅ Creado |
| build.zig | ⏳ Pendiente |
| Fase 1 (Core) | ⏳ Pendiente |
| Fase 2 (Layout) | ⏳ Pendiente |
| Fase 3 (Widgets básicos) | ⏳ Pendiente |
| Fase 4 (Widgets avanzados) | ⏳ Pendiente |
| Fase 5 (Input/extras) | ⏳ Pendiente |
---
**Próximos pasos sugeridos para la primera sesión:**
1. Crear `build.zig` básico
2. Implementar `src/style.zig` (Color, Style, Modifiers)
3. Implementar `src/buffer.zig` (Cell, Buffer, Rect)
4. Implementar `src/backend/ansi.zig` (escape sequences)
5. Crear ejemplo mínimo que pinte algo en pantalla