New modules (13): - src/resize.zig: SIGWINCH terminal resize detection - src/drag.zig: Mouse drag state and Splitter panels - src/diagnostic.zig: Elm-style error messages with code snippets - src/debug.zig: Debug overlay (FPS, timing, widget count) - src/profile.zig: Performance profiling with scoped timers - src/sixel.zig: Sixel graphics encoding for terminal images - src/async_loop.zig: epoll-based async event loop with timers - src/compose.zig: Widget composition utilities - src/shortcuts.zig: Keyboard shortcut registry - src/widgets/logo.zig: ASCII art logo widget Enhanced modules: - src/layout.zig: Added Constraint.ratio(num, denom) - src/terminal.zig: Integrated resize handling - src/root.zig: Re-exports all new modules New examples (9): - resize_demo, splitter_demo, dirtree_demo - help_demo, markdown_demo, progress_demo - spinner_demo, syntax_demo, viewport_demo Package manager: - build.zig.zon: Zig package manager support Stats: 60+ source files, 186+ tests, 20 executables 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
140 lines
3.7 KiB
Zig
140 lines
3.7 KiB
Zig
//! Markdown Viewer Demo
|
|
//!
|
|
//! Run with: zig build markdown-demo
|
|
|
|
const std = @import("std");
|
|
const zcatui = @import("zcatui");
|
|
|
|
const Terminal = zcatui.Terminal;
|
|
const Rect = zcatui.Rect;
|
|
const Buffer = zcatui.Buffer;
|
|
const Style = zcatui.Style;
|
|
const Color = zcatui.Color;
|
|
const Block = zcatui.widgets.Block;
|
|
const Borders = zcatui.widgets.Borders;
|
|
const Markdown = zcatui.widgets.Markdown;
|
|
|
|
const sample_markdown =
|
|
\\# Welcome to zcatui
|
|
\\
|
|
\\A **TUI library** for Zig, inspired by _ratatui_.
|
|
\\
|
|
\\## Features
|
|
\\
|
|
\\- 35+ widgets
|
|
\\- Event handling (keyboard, mouse)
|
|
\\- Animations with easing
|
|
\\- Clipboard support (OSC 52)
|
|
\\- Syntax highlighting
|
|
\\
|
|
\\## Code Example
|
|
\\
|
|
\\```zig
|
|
\\const zcatui = @import("zcatui");
|
|
\\
|
|
\\pub fn main() !void {
|
|
\\ var term = try zcatui.Terminal.init(allocator);
|
|
\\ defer term.deinit();
|
|
\\ // ...
|
|
\\}
|
|
\\```
|
|
\\
|
|
\\## Installation
|
|
\\
|
|
\\Add to your `build.zig.zon`:
|
|
\\
|
|
\\```zon
|
|
\\.dependencies = .{
|
|
\\ .zcatui = .{ .url = "..." },
|
|
\\},
|
|
\\```
|
|
\\
|
|
\\> **Note**: This is a blockquote with important information
|
|
\\> that spans multiple lines.
|
|
\\
|
|
\\### Links
|
|
\\
|
|
\\Check out the [documentation](https://git.reugenio.com/reugenio/zcatui).
|
|
\\
|
|
\\---
|
|
\\
|
|
\\*Thank you for using zcatui!*
|
|
;
|
|
|
|
/// State for the demo
|
|
const State = struct {
|
|
scroll_offset: u16 = 0,
|
|
running: bool = true,
|
|
};
|
|
|
|
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();
|
|
|
|
var state = State{};
|
|
|
|
while (state.running) {
|
|
try term.drawWithContext(&state, render);
|
|
|
|
if (try term.pollEvent(100)) |event| {
|
|
switch (event) {
|
|
.key => |key| {
|
|
switch (key.code) {
|
|
.char => |c| {
|
|
if (c == 'q') state.running = false;
|
|
if (c == 'j') state.scroll_offset +|= 1;
|
|
if (c == 'k' and state.scroll_offset > 0) state.scroll_offset -= 1;
|
|
},
|
|
.up => {
|
|
if (state.scroll_offset > 0) state.scroll_offset -= 1;
|
|
},
|
|
.down => {
|
|
state.scroll_offset +|= 1;
|
|
},
|
|
.page_up => {
|
|
state.scroll_offset -|= 10;
|
|
},
|
|
.page_down => {
|
|
state.scroll_offset +|= 10;
|
|
},
|
|
.home => state.scroll_offset = 0,
|
|
.esc => state.running = false,
|
|
else => {},
|
|
}
|
|
},
|
|
else => {},
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn render(state: *State, area: Rect, buf: *Buffer) void {
|
|
// Border
|
|
const block = Block.init()
|
|
.title(" Markdown Viewer ")
|
|
.setBorders(Borders.all)
|
|
.borderStyle((Style{}).fg(Color.cyan));
|
|
block.render(area, buf);
|
|
|
|
// Markdown content
|
|
const inner = Rect.init(2, 2, area.width -| 4, area.height -| 5);
|
|
|
|
const md = Markdown.init(sample_markdown)
|
|
.setScroll(state.scroll_offset);
|
|
|
|
md.render(inner, buf);
|
|
|
|
// Footer with scroll info
|
|
var footer_buf: [64]u8 = undefined;
|
|
const footer = std.fmt.bufPrint(&footer_buf, "Line {d} | j/k or up/down to scroll, PgUp/PgDn, q to quit", .{state.scroll_offset}) catch "...";
|
|
_ = buf.setString(
|
|
2,
|
|
area.height -| 2,
|
|
footer,
|
|
(Style{}).fg(Color.rgb(100, 100, 100)),
|
|
);
|
|
}
|