zcatui/docs/API.md
reugenio 560ed1b355 zcatui v1.0 - Implementacion completa de todos los widgets ratatui
Widgets implementados (13):
- Block, Paragraph, List, Table
- Gauge, LineGauge, Tabs, Sparkline
- Scrollbar, BarChart, Canvas, Chart
- Calendar (Monthly), Clear

Modulos:
- src/text.zig: Span, Line, Text, Alignment
- src/symbols/: line, border, block, bar, braille, half_block, scrollbar, marker
- src/widgets/: todos los widgets con tests

Documentacion:
- docs/ARCHITECTURE.md: arquitectura tecnica
- docs/WIDGETS.md: guia completa de widgets
- docs/API.md: referencia rapida
- CLAUDE.md: actualizado con estado v1.0

Tests: 103+ tests en widgets, todos pasan

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

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

15 KiB
Raw Blame History

zcatui - API Reference

Referencia rapida de la API publica de zcatui

Importar la Libreria

const zcatui = @import("zcatui");

// Core types
const Color = zcatui.Color;
const Style = zcatui.Style;
const Modifier = zcatui.Modifier;
const Cell = zcatui.Cell;
const Buffer = zcatui.Buffer;
const Rect = zcatui.Rect;
const Span = zcatui.Span;
const Line = zcatui.Line;
const Text = zcatui.Text;
const Alignment = zcatui.Alignment;

// Layout
const Layout = zcatui.Layout;
const Constraint = zcatui.Constraint;
const Direction = zcatui.Direction;

// Terminal
const Terminal = zcatui.Terminal;

// Widgets
const widgets = zcatui.widgets;
const Block = widgets.Block;
const Paragraph = widgets.Paragraph;
const List = widgets.List;
const ListState = widgets.ListState;
// ... etc

Core Types

Color

pub const Color = union(enum) {
    // Reset
    reset,

    // Basic 16 colors
    black, red, green, yellow, blue, magenta, cyan, white,
    light_black, light_red, light_green, light_yellow,
    light_blue, light_magenta, light_cyan, light_white,

    // 256 color palette
    indexed: u8,

    // True color (24-bit)
    rgb: struct { r: u8, g: u8, b: u8 },

    // Constructor helpers
    pub fn indexed(n: u8) Color;
    pub fn rgb(r: u8, g: u8, b: u8) Color;
};

Ejemplos:

const red = Color.red;
const gray = Color.indexed(240);
const custom = Color.rgb(255, 128, 0);

Style

pub const Style = struct {
    foreground: ?Color = null,
    background: ?Color = null,
    add_modifiers: Modifier = .{},
    sub_modifiers: Modifier = .{},

    pub const default: Style = .{};

    // Fluent setters
    pub fn fg(self: Style, color: Color) Style;
    pub fn bg(self: Style, color: Color) Style;
    pub fn bold(self: Style) Style;
    pub fn dim(self: Style) Style;
    pub fn italic(self: Style) Style;
    pub fn underlined(self: Style) Style;
    pub fn slow_blink(self: Style) Style;
    pub fn rapid_blink(self: Style) Style;
    pub fn reversed(self: Style) Style;
    pub fn hidden(self: Style) Style;
    pub fn crossed_out(self: Style) Style;

    // Remove modifiers
    pub fn notBold(self: Style) Style;
    pub fn notDim(self: Style) Style;
    // ... etc

    // Combine styles
    pub fn patch(self: Style, other: Style) Style;
};

Ejemplos:

const style1 = Style.default.fg(Color.red).bold();
const style2 = Style.default.bg(Color.blue).italic();
const combined = style1.patch(style2);  // red fg, blue bg, bold+italic

Modifier

pub const Modifier = packed struct {
    bold: bool = false,
    dim: bool = false,
    italic: bool = false,
    underlined: bool = false,
    slow_blink: bool = false,
    rapid_blink: bool = false,
    reversed: bool = false,
    hidden: bool = false,
    crossed_out: bool = false,

    pub const empty: Modifier = .{};
    pub const all: Modifier = .{ .bold = true, ... };

    pub fn contains(self: Modifier, other: Modifier) bool;
    pub fn insert(self: Modifier, other: Modifier) Modifier;
    pub fn remove(self: Modifier, other: Modifier) Modifier;
};

Rect

pub const Rect = struct {
    x: u16,
    y: u16,
    width: u16,
    height: u16,

    pub fn init(x: u16, y: u16, width: u16, height: u16) Rect;

    // Getters
    pub fn left(self: Rect) u16;    // x
    pub fn right(self: Rect) u16;   // x + width
    pub fn top(self: Rect) u16;     // y
    pub fn bottom(self: Rect) u16;  // y + height
    pub fn area(self: Rect) u32;    // width * height

    // Queries
    pub fn isEmpty(self: Rect) bool;
    pub fn contains(self: Rect, x: u16, y: u16) bool;

    // Transformations
    pub fn inner(self: Rect, margin: u16) Rect;
    pub fn innerMargins(self: Rect, top: u16, right: u16, bottom: u16, left_: u16) Rect;
    pub fn intersection(self: Rect, other: Rect) Rect;
    pub fn union_(self: Rect, other: Rect) Rect;
};

Ejemplos:

const area = Rect.init(0, 0, 80, 24);
const inner = area.inner(1);  // Rect.init(1, 1, 78, 22)

Cell

pub const Cell = struct {
    symbol: Symbol,
    style: Style,

    pub const default_val: Cell = .{ .symbol = Symbol.default_val, .style = Style.default };

    pub fn reset(self: *Cell) void;
    pub fn setChar(self: *Cell, ch: u21) void;
    pub fn setSymbol(self: *Cell, symbol: []const u8) void;
    pub fn setStyle(self: *Cell, style: Style) void;
};

pub const Symbol = struct {
    data: [4]u8,
    len: u3,

    pub const default_val: Symbol;  // " "
    pub fn slice(self: Symbol) []const u8;
};

Buffer

pub const Buffer = struct {
    area: Rect,
    cells: []Cell,
    allocator: Allocator,

    pub fn init(allocator: Allocator, area: Rect) !Buffer;
    pub fn deinit(self: *Buffer) void;
    pub fn empty(area: Rect) Buffer;  // No allocation

    // Cell access
    pub fn getCell(self: *Buffer, x: u16, y: u16) ?*Cell;
    pub fn index(self: Buffer, x: u16, y: u16) ?usize;

    // Setting content
    pub fn setString(self: *Buffer, x: u16, y: u16, text: []const u8, style: Style) u16;
    pub fn setSpan(self: *Buffer, x: u16, y: u16, span: Span, width: u16) u16;
    pub fn setLine(self: *Buffer, x: u16, y: u16, line: Line, width: u16) u16;
    pub fn setStyle(self: *Buffer, area: Rect, style: Style) void;

    // Filling
    pub fn fill(self: *Buffer, cell: Cell) void;
    pub fn fillArea(self: *Buffer, area: Rect, cell: Cell) void;

    // Merging
    pub fn merge(self: *Buffer, other: *const Buffer) void;
};

Ejemplos:

var buf = try Buffer.init(allocator, Rect.init(0, 0, 80, 24));
defer buf.deinit();

_ = buf.setString(10, 5, "Hello, World!", Style.default.fg(Color.green));

if (buf.getCell(10, 5)) |cell| {
    cell.setStyle(Style.default.bold());
}

Text Types

Span

pub const Span = struct {
    content: []const u8,
    style: Style,

    pub fn init(content: []const u8) Span;
    pub fn raw(content: []const u8) Span;
    pub fn styled(content: []const u8, style: Style) Span;
    pub fn setStyle(self: Span, style: Style) Span;
    pub fn width(self: Span) usize;
};

Line

pub const Line = struct {
    spans: []const Span,
    alignment: Alignment,

    pub fn init(spans: []const Span) Line;
    pub fn raw(content: []const u8) Line;
    pub fn styled(content: []const u8, style: Style) Line;
    pub fn setStyle(self: Line, style: Style) Line;
    pub fn setAlignment(self: Line, alignment: Alignment) Line;
    pub fn width(self: Line) usize;
};

Text

pub const Text = struct {
    lines: []const Line,
    alignment: Alignment,

    pub fn init(lines: []const Line) Text;
    pub fn raw(content: []const u8) Text;
    pub fn styled(content: []const u8, style: Style) Text;
    pub fn setStyle(self: Text, style: Style) Text;
    pub fn setAlignment(self: Text, alignment: Alignment) Text;
    pub fn width(self: Text) usize;
    pub fn height(self: Text) usize;
};

Alignment

pub const Alignment = enum {
    left,
    center,
    right,
};

Ejemplos:

// Simple text
const span = Span.styled("Hello", Style.default.fg(Color.red));
const line = Line.raw("Simple line");

// Multi-span line
const multi_line = Line.init(&[_]Span{
    Span.styled("Error: ", Style.default.fg(Color.red).bold()),
    Span.raw("Something went wrong"),
});

// Multi-line text
const text = Text.raw("Line 1\nLine 2\nLine 3");

Layout

Layout

pub const Layout = struct {
    direction: Direction,
    constraints: []const Constraint,

    pub fn horizontal(constraints: []const Constraint) Layout;
    pub fn vertical(constraints: []const Constraint) Layout;
    pub fn init(direction: Direction, constraints: []const Constraint) Layout;

    pub fn split(self: Layout, area: Rect, result: []Rect) void;
};

Constraint

pub 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 (0-100)
    ratio: struct { num: u32, den: u32 },
    fill: u16,        // Fill remaining space (weight)

    pub fn length(n: u16) Constraint;
    pub fn min(n: u16) Constraint;
    pub fn max(n: u16) Constraint;
    pub fn percentage(n: u16) Constraint;
    pub fn ratio(num: u32, den: u32) Constraint;
    pub fn fill(weight: u16) Constraint;
};

Direction

pub const Direction = enum {
    horizontal,
    vertical,
};

Ejemplos:

// Vertical layout: header (3 rows), content (rest), footer (1 row)
const layout = Layout.vertical(&[_]Constraint{
    Constraint.length(3),
    Constraint.min(0),
    Constraint.length(1),
});

var chunks: [3]Rect = undefined;
layout.split(area, &chunks);

// Horizontal split: 30% | 70%
const h_layout = Layout.horizontal(&[_]Constraint{
    Constraint.percentage(30),
    Constraint.percentage(70),
});

Symbols

Line Set

pub const line = struct {
    pub const Set = struct {
        vertical: []const u8,
        horizontal: []const u8,
        top_right: []const u8,
        top_left: []const u8,
        bottom_right: []const u8,
        bottom_left: []const u8,
        vertical_left: []const u8,
        vertical_right: []const u8,
        horizontal_down: []const u8,
        horizontal_up: []const u8,
        cross: []const u8,
    };

    pub const NORMAL: Set;   // ─│┌┐└┘
    pub const ROUNDED: Set;  // ─│╭╮╰╯
    pub const DOUBLE: Set;   // ═║╔╗╚╝
    pub const THICK: Set;    // ━┃┏┓┗┛
};

Border Set

pub const border = struct {
    pub const Set = struct {
        top_left: []const u8,
        top_right: []const u8,
        bottom_left: []const u8,
        bottom_right: []const u8,
        horizontal: []const u8,
        vertical: []const u8,
    };

    pub const PLAIN: Set;
    pub const ROUNDED: Set;
    pub const DOUBLE: Set;
    pub const THICK: Set;
};

Block Characters

pub const block = struct {
    pub const FULL: []const u8 = "█";
    pub const UPPER_HALF: []const u8 = "▀";
    pub const LOWER_HALF: []const u8 = "▄";
    pub const LEFT_HALF: []const u8 = "▌";
    pub const RIGHT_HALF: []const u8 = "▐";
    // ...
};

Bar Characters

pub const bar = struct {
    pub const Set = struct {
        full: []const u8,
        seven_eighths: []const u8,
        three_quarters: []const u8,
        five_eighths: []const u8,
        half: []const u8,
        three_eighths: []const u8,
        one_quarter: []const u8,
        one_eighth: []const u8,
        empty: []const u8,
    };

    pub const NINE_LEVELS: Set;
    pub const THREE_LEVELS: Set;
};

Braille

pub const braille = struct {
    pub const BLANK: []const u8 = "";  // U+2800

    // Bit positions for 2x4 grid:
    // 0 3
    // 1 4
    // 2 5
    // 6 7

    pub const PATTERNS: [256][3]u8;  // Pre-computed UTF-8 patterns

    pub fn fromPattern(pattern: u8) []const u8;
};

Marker

pub const Marker = enum {
    dot,
    block,
    bar,
    braille,
    half_block,
};

Terminal

pub const Terminal = struct {
    pub fn init(allocator: Allocator) !Terminal;
    pub fn deinit(self: *Terminal) void;

    pub fn size(self: Terminal) struct { width: u16, height: u16 };
    pub fn area(self: Terminal) Rect;

    pub fn draw(self: *Terminal, render_fn: fn(area: Rect, buf: *Buffer) void) !void;
    pub fn clear(self: *Terminal) !void;
    pub fn flush(self: *Terminal) !void;

    pub fn hideCursor(self: *Terminal) !void;
    pub fn showCursor(self: *Terminal) !void;
    pub fn setCursorPosition(self: *Terminal, x: u16, y: u16) !void;

    pub fn enterAlternateScreen(self: *Terminal) !void;
    pub fn leaveAlternateScreen(self: *Terminal) !void;

    pub fn enableRawMode(self: *Terminal) !void;
    pub fn disableRawMode(self: *Terminal) !void;
};

Ejemplo de uso:

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var term = try Terminal.init(allocator);
    defer term.deinit();

    try term.enterAlternateScreen();
    defer term.leaveAlternateScreen() catch {};

    try term.hideCursor();
    defer term.showCursor() catch {};

    try term.draw(struct {
        pub fn render(area: Rect, buf: *Buffer) void {
            const block = Block.bordered().title("Hello zcatui!");
            block.render(area, buf);
        }
    }.render);

    // Wait for input...
}

Widgets Quick Reference

Widget Constructor Stateful Key Methods
Block Block.init() No title(), borders(), borderStyle()
Paragraph Paragraph.init(text) No setWrap(), setAlignment(), setScroll()
List List.init(items) Yes setHighlightStyle(), setHighlightSymbol()
Table Table.init(rows, widths) Yes setHeader(), setHighlightStyle()
Gauge Gauge.init() No setRatio(), setPercent(), setLabel()
LineGauge LineGauge.init() No setRatio(), setFilledStyle()
Tabs Tabs.init(titles) No select(), setDivider()
Sparkline Sparkline.init() No setData(), setMax()
Scrollbar Scrollbar.init(orientation) Yes setSymbols(), setStyle()
BarChart BarChart.init() No setData(), setBarWidth()
Canvas Canvas.init() No setXBounds(), setYBounds(), paint()
Chart Chart.init(datasets) No setXAxis(), setYAxis()
Monthly Monthly.init(date) No showMonthHeader(), showWeekdaysHeader()
Clear Clear.init() No (none)

Error Handling

zcatui usa el sistema de errores de Zig. Las funciones que pueden fallar retornan !T.

// Errores comunes
const TerminalError = error{
    InitFailed,
    WriteFailed,
    FlushFailed,
};

const BufferError = error{
    OutOfMemory,
};

// Manejo tipico
var term = Terminal.init(allocator) catch |err| {
    std.debug.print("Failed to init terminal: {}\n", .{err});
    return err;
};
defer term.deinit();

Patterns

Builder Pattern

const widget = SomeWidget.init()
    .setOption1(value1)
    .setOption2(value2)
    .setBlock(Block.bordered());

Stateful Rendering

var state = WidgetState.init();

// En el loop de renderizado:
widget.renderStateful(area, buf, &state);

// Actualizar estado basado en input:
state.selectNext(items.len);

Layout Composition

const outer = Layout.vertical(&[_]Constraint{
    Constraint.length(3),
    Constraint.min(0),
});

var outer_chunks: [2]Rect = undefined;
outer.split(area, &outer_chunks);

const inner = Layout.horizontal(&[_]Constraint{
    Constraint.percentage(50),
    Constraint.percentage(50),
});

var inner_chunks: [2]Rect = undefined;
inner.split(outer_chunks[1], &inner_chunks);