this repo has no description
1const std = @import("std");
2const vaxis = @import("vaxis");
3const Cell = vaxis.Cell;
4
5const log = std.log.scoped(.main);
6pub fn main(init: std.process.Init) !void {
7 const io = init.io;
8 const alloc = init.gpa;
9
10 var buffer: [1024]u8 = undefined;
11 var tty = try vaxis.Tty.init(io, &buffer);
12 defer tty.deinit();
13
14 var vx = try vaxis.init(io, alloc, init.environ_map, .{});
15 defer vx.deinit(alloc, tty.writer());
16
17 var loop: vaxis.Loop(Event) = .init(io, &tty, &vx);
18
19 try loop.start();
20 defer loop.stop();
21
22 // Optionally enter the alternate screen
23 try vx.enterAltScreen(tty.writer());
24 try vx.queryTerminal(tty.writer(), .fromSeconds(1));
25
26 // We'll adjust the color index every keypress
27 var color_idx: u8 = 0;
28 const msg = "Hello, world!";
29
30 var scale: u3 = 1;
31
32 // The main event loop. Vaxis provides a thread safe, blocking, buffered
33 // queue which can serve as the primary event queue for an application
34 while (true) {
35 // nextEvent blocks until an event is in the queue
36 const event = try loop.nextEvent();
37 // log.debug("event: {}", .{event});
38 // exhaustive switching ftw. Vaxis will send events if your Event
39 // enum has the fields for those events (ie "key_press", "winsize")
40 switch (event) {
41 .key_press => |key| {
42 color_idx = switch (color_idx) {
43 255 => 0,
44 else => color_idx + 1,
45 };
46 if (key.codepoint == 'c' and key.mods.ctrl) {
47 break;
48 }
49 if (key.matches('j', .{})) {
50 if (vx.caps.scaled_text and scale > 1) {
51 scale -= 1;
52 }
53 }
54 if (key.matches('k', .{})) {
55 if (vx.caps.scaled_text and scale < 7) {
56 scale += 1;
57 }
58 }
59 },
60 .winsize => |ws| {
61 try vx.resize(alloc, tty.writer(), ws);
62 },
63 else => {},
64 }
65
66 // vx.window() returns the root window. This window is the size of the
67 // terminal and can spawn child windows as logical areas. Child windows
68 // cannot draw outside of their bounds
69 const win = vx.window();
70 // Clear the entire space because we are drawing in immediate mode.
71 // vaxis double buffers the screen. This new frame will be compared to
72 // the old and only updated cells will be drawn
73 win.clear();
74
75 const msg_len: u16 = @intCast(msg.len);
76 // Create some child window. .expand means the height and width will
77 // fill the remaining space of the parent. Child windows do not store a
78 // reference to their parent: this is true immediate mode. Do not store
79 // windows, always create new windows each render cycle
80 const child = win.child(
81 .{ .x_off = win.width / 2 - msg_len / 2, .y_off = win.height / 2 },
82 );
83 // Loop through the message and print the cells to the screen
84 for (msg, 0..) |_, i| {
85 const cell: Cell = .{
86 // each cell takes a _grapheme_ as opposed to a single
87 // codepoint. This allows Vaxis to handle emoji properly,
88 // particularly with terminals that the Unicode Core extension
89 // (IE Mode 2027)
90 .char = .{ .grapheme = msg[i .. i + 1] },
91 .style = .{
92 .fg = .{ .index = color_idx },
93 },
94 .scale = .{
95 .scale = scale,
96 },
97 };
98 const second_cell: Cell = .{
99 .char = .{ .grapheme = msg[i .. i + 1] },
100 .style = .{
101 .fg = .{ .index = color_idx },
102 },
103 };
104 child.writeCell(@intCast(i * scale), 0, cell);
105 child.writeCell(@intCast(i), scale - 1, second_cell);
106 child.writeCell(@intCast(i), scale, second_cell);
107 }
108 // Render the screen
109 try vx.render(tty.writer());
110 }
111}
112
113// Our Event. This can contain internal events as well as Vaxis events.
114// Internal events can be posted into the same queue as vaxis events to allow
115// for a single event loop with exhaustive switching. Booya
116const Event = union(enum) {
117 key_press: vaxis.Key,
118 winsize: vaxis.Winsize,
119 focus_in,
120 foo: u8,
121};
122
123test {
124 std.testing.refAllDecls(@This());
125}