All checks were successful
Zig Project Action / Lint, Spell-check and test zig project (push) Successful in 33s
The implementation of `Layout.Framing` however does not use the renderer and instead writes directly to the terminal (which it should not and instead use the renderer). The example has been enhanced with both usage of `Layout.Framing` and `Layout.Padding` Layouts to showcase the `Layout` implementations.
123 lines
4.7 KiB
Zig
123 lines
4.7 KiB
Zig
const std = @import("std");
|
|
const zterm = @import("zterm");
|
|
|
|
const App = zterm.App(
|
|
union(enum) {},
|
|
zterm.Renderer.Direct,
|
|
true,
|
|
);
|
|
const Key = zterm.Key;
|
|
const Layout = App.Layout;
|
|
const Widget = App.Widget;
|
|
|
|
const log = std.log.scoped(.default);
|
|
|
|
pub fn main() !void {
|
|
errdefer |err| log.err("Application Error: {any}", .{err});
|
|
|
|
var gpa: std.heap.GeneralPurposeAllocator(.{}) = .{};
|
|
defer {
|
|
const deinit_status = gpa.deinit();
|
|
// fail test; can't try in defer as defer is executed after we return
|
|
if (deinit_status == .leak) {
|
|
log.err("memory leak", .{});
|
|
}
|
|
}
|
|
const allocator = gpa.allocator();
|
|
|
|
var app: App = .{};
|
|
const renderer: App.Renderer = .{};
|
|
// FIX: when not running fullscreen, the application needs to screen down accordingly to display the contents
|
|
// -> size hint how much should it use?
|
|
|
|
var layout = Layout.createFrom(layout: {
|
|
var hstack = Layout.HStack.init(allocator, .{
|
|
Widget.createFrom(blk: {
|
|
var spacer = Widget.Spacer.init();
|
|
break :blk &spacer;
|
|
}),
|
|
Layout.createFrom(framing: {
|
|
var framing = Layout.Framing.init(allocator, .{
|
|
.layout = Layout.createFrom(
|
|
padding: {
|
|
var padding = Layout.Padding.init(allocator, 2, .{
|
|
.layout = Layout.createFrom(vstack: {
|
|
var vstack = Layout.VStack.init(allocator, .{
|
|
Widget.createFrom(blk: {
|
|
const file = try std.fs.cwd().openFile("./src/app.zig", .{});
|
|
defer file.close();
|
|
var widget = Widget.RawText.init(allocator, file);
|
|
break :blk &widget;
|
|
}),
|
|
Widget.createFrom(blk: {
|
|
var spacer = Widget.Spacer.init();
|
|
break :blk &spacer;
|
|
}),
|
|
Widget.createFrom(blk: {
|
|
const file = try std.fs.cwd().openFile("./src/main.zig", .{});
|
|
defer file.close();
|
|
var widget = Widget.RawText.init(allocator, file);
|
|
break :blk &widget;
|
|
}),
|
|
});
|
|
break :vstack &vstack;
|
|
}),
|
|
});
|
|
break :padding &padding;
|
|
},
|
|
),
|
|
});
|
|
break :framing &framing;
|
|
}),
|
|
Widget.createFrom(blk: {
|
|
var spacer = Widget.Spacer.init();
|
|
break :blk &spacer;
|
|
}),
|
|
});
|
|
break :layout &hstack;
|
|
});
|
|
defer layout.deinit();
|
|
|
|
try app.start();
|
|
defer app.stop() catch unreachable;
|
|
|
|
// App.Event loop
|
|
while (true) {
|
|
const event = app.nextEvent();
|
|
log.debug("received event: {s}", .{@tagName(event)});
|
|
|
|
switch (event) {
|
|
.quit => break,
|
|
.key => |key| {
|
|
// ctrl+c to quit
|
|
if (Key.matches(key, .{ .cp = 'c', .mod = .{ .ctrl = true } })) {
|
|
app.quit();
|
|
}
|
|
if (Key.matches(key, .{ .cp = 'n', .mod = .{ .ctrl = true } })) {
|
|
try app.interrupt();
|
|
defer app.start() catch @panic("could not start app event loop");
|
|
var child = std.process.Child.init(&.{"hx"}, allocator);
|
|
_ = child.spawnAndWait() catch |err| {
|
|
app.postEvent(.{
|
|
.err = .{
|
|
.err = err,
|
|
.msg = "Spawning Helix failed",
|
|
},
|
|
});
|
|
};
|
|
}
|
|
},
|
|
.err => |err| {
|
|
log.err("Received {any} with message: {s}", .{ err.err, err.msg });
|
|
},
|
|
else => {},
|
|
}
|
|
// NOTE: this currently re-renders the screen for every key-press -> which might be a bit of an overkill
|
|
const events = try layout.handle(event);
|
|
for (events.items) |e| {
|
|
app.postEvent(e);
|
|
}
|
|
try layout.render(renderer);
|
|
}
|
|
}
|