-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathmarkdown.zig
More file actions
102 lines (88 loc) · 3.01 KB
/
Copy pathmarkdown.zig
File metadata and controls
102 lines (88 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//! ZigZag Markdown Renderer Example
//! Demonstrates rendering markdown to styled terminal output.
const std = @import("std");
const zz = @import("zigzag");
const sample_md =
\\# ZigZag TUI Framework
\\
\\A **modern** TUI library for *Zig* inspired by Bubble Tea and Lipgloss.
\\
\\## Features
\\
\\- Elm architecture (Model-Update-View)
\\- Rich **component library**
\\- `Style` builder with *colors* and borders
\\- Cross-platform terminal support
\\
\\### Getting Started
\\
\\1. Add ZigZag to your `build.zig.zon`
\\2. Import with `const zz = @import("zigzag")`
\\3. Create a `Model` struct with `init`, `update`, `view`
\\
\\> ZigZag makes terminal UI development feel natural and productive.
\\> Build beautiful TUIs with minimal boilerplate.
\\
\\---
\\
\\```
\\const std = @import("std");
\\const zz = @import("zigzag");
\\
\\pub fn main() !void {
\\ var program = zz.Program(Model).init(allocator);
\\ try program.run();
\\}
\\```
\\
\\Check out the [documentation](https://github.com/meszmate/zigzag) for more.
;
const Model = struct {
md: zz.Markdown,
viewport: zz.components.Viewport,
pub const Msg = union(enum) {
key: zz.KeyEvent,
};
pub fn init(self: *Model, ctx: *zz.Context) !zz.Cmd(Msg) {
self.md = zz.Markdown.init();
self.md.width = @min(ctx.width -| 4, 80);
self.viewport = zz.components.Viewport.init(ctx.persistent_allocator, self.md.width, ctx.height -| 4);
// Viewport.setContent dupes; render output is ephemeral.
if (self.md.render(ctx.persistent_allocator, sample_md)) |rendered| {
defer ctx.persistent_allocator.free(rendered);
try self.viewport.setContent(rendered);
} else |_| {
try self.viewport.setContent("render error");
}
return .none;
}
pub fn update(self: *Model, msg: Msg, _: *zz.Context) zz.Cmd(Msg) {
switch (msg) {
.key => |k| {
switch (k.key) {
.char => |c| if (c == 'q') return .quit,
.escape => return .quit,
else => {},
}
self.viewport.handleKey(k);
},
}
return .none;
}
pub fn view(self: *const Model, ctx: *const zz.Context) ![]const u8 {
const content = try self.viewport.view(ctx.allocator);
var help_style = zz.Style{};
help_style = help_style.fg(zz.Color.gray(12));
help_style = help_style.inline_style(true);
const help = try help_style.render(ctx.allocator, "j/k or Up/Down: scroll | q: quit");
return std.fmt.allocPrint(ctx.allocator, "{s}\n{s}", .{ content, help });
}
pub fn deinit(self: *Model) void {
self.viewport.deinit();
}
};
pub fn main(init: std.process.Init) !void {
var program = zz.Program(Model).init(init.gpa, init.io, init.environ_map);
defer program.deinit();
try program.run();
}