feat: add libvaxis renderer

This commit is contained in:
CJ van den Berg 2024-05-01 22:03:33 +02:00
parent b15fa47f30
commit 1cd3cb17ce
32 changed files with 1559 additions and 516 deletions

View file

@ -33,21 +33,21 @@ on_resize: *const fn (ctx: ?*anyopaque, self: *Self, pos_: Widget.Box) void = on
pub fn createH(a: Allocator, parent: Widget, name: [:0]const u8, layout_: Layout) !*Self {
const self: *Self = try a.create(Self);
self.* = try init(a, parent, name, .horizontal, layout_, Box{});
self.plane.move_bottom();
self.plane.hide();
return self;
}
pub fn createV(a: Allocator, parent: Widget, name: [:0]const u8, layout_: Layout) !*Self {
const self: *Self = try a.create(Self);
self.* = try init(a, parent, name, .vertical, layout_, Box{});
self.plane.move_bottom();
self.plane.hide();
return self;
}
pub fn createBox(a: Allocator, parent: Widget, name: [:0]const u8, dir: Direction, layout_: Layout, box: Box) !*Self {
const self: *Self = try a.create(Self);
self.* = try init(a, parent, name, dir, layout_, box);
self.plane.move_bottom();
self.plane.hide();
return self;
}

File diff suppressed because it is too large Load diff

View file

@ -1,17 +1,18 @@
const Plane = @import("renderer").Plane;
const Style = @import("theme").Style;
pub fn print_string_large(n: Plane, s: []const u8) !void {
pub fn print_string_large(n: *Plane, s: []const u8, style: Style) !void {
for (s) |c|
print_char_large(n, c) catch break;
print_char_large(n, c, style) catch break;
}
pub fn print_char_large(n: Plane, char: u8) !void {
pub fn print_char_large(n: *Plane, char: u8, style: Style) !void {
const bitmap = font8x8[char];
for (0..8) |y| {
for (0..8) |x| {
const set = bitmap[y] & @as(usize, 1) << @intCast(x);
if (set != 0) {
_ = try n.putstr("");
try write_cell(n, "", style);
} else {
n.cursor_move_rel(0, 1) catch {};
}
@ -21,14 +22,14 @@ pub fn print_char_large(n: Plane, char: u8) !void {
n.cursor_move_rel(-8, 8) catch {};
}
pub fn print_string_medium(n: Plane, s: []const u8) !void {
pub fn print_string_medium(n: *Plane, s: []const u8, style: Style) !void {
for (s) |c|
print_char_medium(n, c) catch break;
print_char_medium(n, c, style) catch break;
}
const QUADBLOCKS = [_][:0]const u8{ " ", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" };
pub fn print_char_medium(n: Plane, char: u8) !void {
pub fn print_char_medium(n: *Plane, char: u8, style: Style) !void {
const bitmap = font8x8[char];
for (0..4) |y| {
for (0..4) |x| {
@ -43,7 +44,7 @@ pub fn print_char_medium(n: Plane, char: u8) !void {
const quadidx: u4 = setbr | setbl | settr | settl;
const c = QUADBLOCKS[quadidx];
if (quadidx != 0) {
_ = try n.putstr(c);
try write_cell(n, c, style);
} else {
n.cursor_move_rel(0, 1) catch {};
}
@ -53,6 +54,14 @@ pub fn print_char_medium(n: Plane, char: u8) !void {
n.cursor_move_rel(-4, 4) catch {};
}
fn write_cell(n: *Plane, egc: [:0]const u8, style: Style) !void {
var cell = n.cell_init();
_ = n.at_cursor_cell(&cell) catch return;
_ = n.cell_load(&cell, egc) catch {};
cell.set_style_fg(style);
_ = n.putc(&cell) catch {};
}
pub const font8x8: [128][8]u8 = [128][8]u8{
[8]u8{ 0, 0, 0, 0, 0, 0, 0, 0 },
[8]u8{ 0, 0, 0, 0, 0, 0, 0, 0 },

View file

@ -15,7 +15,6 @@ const command = @import("command.zig");
const fonts = @import("fonts.zig");
a: std.mem.Allocator,
background: Plane,
plane: Plane,
parent: Plane,
fire: ?Fire = null,
@ -26,8 +25,6 @@ const Self = @This();
pub fn create(a: std.mem.Allocator, parent: Widget) !Widget {
const self: *Self = try a.create(Self);
var background = try Plane.init(&(Widget.Box{}).opts("background"), parent.plane.*);
errdefer background.deinit();
var n = try Plane.init(&(Widget.Box{}).opts("editor"), parent.plane.*);
errdefer n.deinit();
@ -35,7 +32,6 @@ pub fn create(a: std.mem.Allocator, parent: Widget) !Widget {
self.* = .{
.a = a,
.parent = parent.plane.*,
.background = background,
.plane = n,
.menu = try Menu.create(*Self, a, w, .{ .ctx = self, .on_render = menu_on_render }),
};
@ -56,7 +52,6 @@ pub fn deinit(self: *Self, a: std.mem.Allocator) void {
self.menu.deinit(a);
self.commands.deinit();
self.plane.deinit();
self.background.deinit();
if (self.fire) |*fire| fire.deinit();
a.destroy(self);
}
@ -130,16 +125,13 @@ fn menu_action_quit(_: **Menu.State(*Self), _: *Button.State(*Menu.State(*Self))
}
pub fn render(self: *Self, theme: *const Widget.Theme) bool {
const more = self.menu.render(theme);
self.background.set_base_style(" ", theme.editor);
self.background.erase();
self.background.home();
self.plane.set_base_style_transparent("", theme.editor);
self.plane.erase();
self.plane.home();
if (self.fire) |*fire| fire.render();
const more = self.menu.render(theme);
const style_title = if (tui.find_scope_style(theme, "function")) |sty| sty.style else theme.editor;
const style_subtext = if (tui.find_scope_style(theme, "comment")) |sty| sty.style else theme.editor;
@ -147,19 +139,16 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool {
const subtext = "a programmer's text editor";
if (self.plane.dim_x() > 120 and self.plane.dim_y() > 22) {
self.plane.set_style_bg_transparent(style_title);
self.plane.cursor_move_yx(2, 4) catch return more;
fonts.print_string_large(self.plane, title) catch return more;
fonts.print_string_large(&self.plane, title, style_title) catch return more;
self.plane.set_style_bg_transparent(style_subtext);
self.plane.cursor_move_yx(10, 8) catch return more;
fonts.print_string_medium(self.plane, subtext) catch return more;
fonts.print_string_medium(&self.plane, subtext, style_subtext) catch return more;
self.menu.resize(.{ .y = 15, .x = 10, .w = 32 });
} else if (self.plane.dim_x() > 55 and self.plane.dim_y() > 16) {
self.plane.set_style_bg_transparent(style_title);
self.plane.cursor_move_yx(2, 4) catch return more;
fonts.print_string_medium(self.plane, title) catch return more;
fonts.print_string_medium(&self.plane, title, style_title) catch return more;
self.plane.set_style_bg_transparent(style_subtext);
self.plane.cursor_move_yx(7, 6) catch return more;
@ -181,13 +170,11 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool {
}
pub fn handle_resize(self: *Self, pos: Widget.Box) void {
self.background.move_yx(@intCast(pos.y), @intCast(pos.x)) catch return;
self.background.resize_simple(@intCast(pos.h), @intCast(pos.w)) catch return;
self.plane.move_yx(@intCast(pos.y), @intCast(pos.x)) catch return;
self.plane.resize_simple(@intCast(pos.h), @intCast(pos.w)) catch return;
if (self.fire) |*fire| {
fire.deinit();
self.fire = Fire.init(self.a, self.plane, pos) catch return;
self.fire = Fire.init(self.a, self.plane) catch return;
}
}
@ -213,7 +200,7 @@ const cmds = struct {
self.fire = if (self.fire) |*fire| ret: {
fire.deinit();
break :ret null;
} else Fire.init(self.a, self.background, Widget.Box.from(self.background)) catch |e| return tp.exit_error(e);
} else Fire.init(self.a, self.plane) catch |e| return tp.exit_error(e);
}
};
@ -239,7 +226,8 @@ const Fire = struct {
const MAX_COLOR = 256;
const LAST_COLOR = MAX_COLOR - 1;
fn init(a: std.mem.Allocator, plane: Plane, pos: Widget.Box) !Fire {
fn init(a: std.mem.Allocator, plane: Plane) !Fire {
const pos = Widget.Box.from(plane);
const FIRE_H = @as(u16, @intCast(pos.h)) * 2;
const FIRE_W = @as(u16, @intCast(pos.w));
var self: Fire = .{

View file

@ -99,11 +99,11 @@ fn inspect_location(self: *Self, row: usize, col: usize) void {
fn get_buffer_text(self: *Self, buf: []u8, sel: Buffer.Selection) ?[]const u8 {
const root = self.editor.get_current_root() orelse return null;
return root.get_range(sel, buf, null, null) catch return null;
return root.get_range(sel, buf, null, null, self.plane) catch return null;
}
fn dump_highlight(self: *Self, range: syntax.Range, scope: []const u8, id: u32, _: usize, ast_node: *const syntax.Node) error{Stop}!void {
const sel = self.pos_cache.range_to_selection(range, self.editor.get_current_root() orelse return) orelse return;
const sel = self.pos_cache.range_to_selection(range, self.editor.get_current_root() orelse return, self.plane) orelse return;
if (self.need_clear) {
self.need_clear = false;
self.clear();
@ -138,7 +138,7 @@ fn dump_highlight(self: *Self, range: syntax.Range, scope: []const u8, id: u32,
const ast_parent = parent.asSExpressionString();
_ = self.plane.print("parent: {s}\n", .{ast_parent}) catch {};
syntax.Node.freeSExpressionString(ast_parent);
const sel_parent = self.pos_cache.range_to_selection(parent.getRange(), self.editor.get_current_root() orelse return) orelse return;
const sel_parent = self.pos_cache.range_to_selection(parent.getRange(), self.editor.get_current_root() orelse return, self.plane) orelse return;
var match_parent = ed.Match.from_selection(sel_parent);
if (self.theme) |theme| match_parent.style = .{ .bg = theme.editor_gutter_added.fg };
switch (update_match) {

View file

@ -4,7 +4,7 @@ const root = @import("root");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const egc_ = @import("renderer").egc;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const tui = @import("../../tui.zig");
const command = @import("../../command.zig");
@ -250,7 +250,7 @@ fn insert_code_point(self: *Self, c: u32) tp.result {
if (self.input.items.len + 4 > input_buffer_size)
try self.flush_input();
var buf: [6]u8 = undefined;
const bytes = egc_.ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
}

View file

@ -4,7 +4,7 @@ const root = @import("root");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const egc_ = @import("renderer").egc;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const tui = @import("../../../tui.zig");
const command = @import("../../../command.zig");
@ -251,7 +251,7 @@ fn insert_code_point(self: *Self, c: u32) tp.result {
if (self.input.items.len + 4 > input_buffer_size)
try self.flush_input();
var buf: [6]u8 = undefined;
const bytes = egc_.ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
}

View file

@ -4,7 +4,7 @@ const root = @import("root");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const egc_ = @import("renderer").egc;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const tui = @import("../../../tui.zig");
const command = @import("../../../command.zig");
@ -453,7 +453,7 @@ fn insert_code_point(self: *Self, c: u32) tp.result {
if (self.input.items.len + 4 > input_buffer_size)
try self.flush_input();
var buf: [6]u8 = undefined;
const bytes = egc_.ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
}

View file

@ -4,7 +4,7 @@ const root = @import("root");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const egc_ = @import("renderer").egc;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const tui = @import("../../../tui.zig");
const command = @import("../../../command.zig");
@ -411,7 +411,7 @@ fn insert_code_point(self: *Self, c: u32) tp.result {
if (self.input.items.len + 4 > input_buffer_size)
try self.flush_input();
var buf: [6]u8 = undefined;
const bytes = egc_.ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
self.input.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
}

View file

@ -3,7 +3,7 @@ const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const egc_ = @import("renderer").egc;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const tui = @import("../../tui.zig");
const mainview = @import("../../mainview.zig");
@ -161,7 +161,7 @@ fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
fn insert_code_point(self: *Self, c: u32) tp.result {
if (self.input.len + 16 > self.buf.len)
try self.flush_input();
const bytes = egc_.ucs32_to_utf8(&[_]u32{c}, self.buf[self.input.len..]) catch |e| return tp.exit_error(e);
const bytes = ucs32_to_utf8(&[_]u32{c}, self.buf[self.input.len..]) catch |e| return tp.exit_error(e);
self.input = self.buf[0 .. self.input.len + bytes];
}

View file

@ -3,7 +3,7 @@ const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const egc_ = @import("renderer").egc;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const tui = @import("../../tui.zig");
const mainview = @import("../../mainview.zig");
@ -158,7 +158,7 @@ fn mapRelease(self: *Self, keypress: u32, _: u32, _: u32) tp.result {
fn insert_code_point(self: *Self, c: u32) tp.result {
if (self.input.len + 16 > self.buf.len)
try self.flush_input();
const bytes = egc_.ucs32_to_utf8(&[_]u32{c}, self.buf[self.input.len..]) catch |e| return tp.exit_error(e);
const bytes = ucs32_to_utf8(&[_]u32{c}, self.buf[self.input.len..]) catch |e| return tp.exit_error(e);
self.input = self.buf[0 .. self.input.len + bytes];
}

View file

@ -3,7 +3,7 @@ const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const egc_ = @import("renderer").egc;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const tui = @import("../../tui.zig");
const mainview = @import("../../mainview.zig");
@ -114,7 +114,7 @@ fn execute_operation(self: *Self, c: u32) void {
},
};
var buf: [6]u8 = undefined;
const bytes = egc_.ucs32_to_utf8(&[_]u32{c}, &buf) catch return;
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch return;
command.executeName(cmd, command.fmt(.{buf[0..bytes]})) catch {};
command.executeName("exit_mini_mode", .{}) catch {};
}

View file

@ -4,7 +4,7 @@ const tp = @import("thespian");
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const egc_ = @import("renderer").egc;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const tui = @import("../../tui.zig");
const mainview = @import("../../mainview.zig");
@ -125,7 +125,7 @@ fn mapRelease(_: *Self, _: u32, _: u32, _: u32) tp.result {}
fn insert_code_point(self: *Self, c: u32) tp.result {
var buf: [32]u8 = undefined;
const bytes = egc_.ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
self.file_path.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
}

View file

@ -8,7 +8,7 @@ const planeutils = @import("renderer").planeutils;
const key = @import("renderer").input.key;
const mod = @import("renderer").input.modifier;
const event_type = @import("renderer").input.event_type;
const egc_ = @import("renderer").egc;
const ucs32_to_utf8 = @import("renderer").ucs32_to_utf8;
const tui = @import("../../tui.zig");
const command = @import("../../command.zig");
@ -89,13 +89,13 @@ fn on_render_menu(_: *Self, button: *Button.State(*Menu.State(*Self)), theme: *c
var len = cbor.decodeArrayHeader(&iter) catch return false;
while (len > 0) : (len -= 1) {
if (cbor.matchValue(&iter, cbor.extract(&index)) catch break) {
render_cell(button.plane, 0, index + 1, theme.editor_match) catch break;
render_cell(&button.plane, 0, index + 1, theme.editor_match) catch break;
} else break;
}
return false;
}
fn render_cell(plane: Plane, y: usize, x: usize, style: Widget.Theme.Style) !void {
fn render_cell(plane: *Plane, y: usize, x: usize, style: Widget.Theme.Style) !void {
plane.cursor_move_yx(@intCast(y), @intCast(x)) catch return;
var cell = plane.cell_init();
_ = plane.at_cursor_cell(&cell) catch return;
@ -313,7 +313,7 @@ fn delete_code_point(self: *Self) tp.result {
fn insert_code_point(self: *Self, c: u32) tp.result {
var buf: [6]u8 = undefined;
const bytes = egc_.ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
const bytes = ucs32_to_utf8(&[_]u32{c}, &buf) catch |e| return tp.exit_error(e);
self.inputbox.text.appendSlice(buf[0..bytes]) catch |e| return tp.exit_error(e);
self.inputbox.cursor = self.inputbox.text.items.len;
return self.start_query();

View file

@ -123,7 +123,7 @@ pub fn render(self: *Self, theme: *const Widget.Theme) bool {
defer frame.deinit();
self.plane.set_base_style(" ", if (self.active) theme.scrollbar_active else if (self.hover) theme.scrollbar_hover else theme.scrollbar);
self.plane.erase();
smooth_bar_at(self.plane, @intCast(self.pos_scrn), @intCast(self.view_scrn)) catch {};
smooth_bar_at(&self.plane, @intCast(self.pos_scrn), @intCast(self.view_scrn)) catch {};
return false;
}
@ -151,7 +151,7 @@ const eighths_b = [_][]const u8{ "█", "▇", "▆", "▅", "▄", "▃", "▂"
const eighths_t = [_][]const u8{ " ", "", "🮂", "🮃", "", "🮄", "🮅", "🮆" };
const eighths_c: i32 = @intCast(eighths_b.len);
fn smooth_bar_at(plane: Plane, pos_: i32, size_: i32) !void {
fn smooth_bar_at(plane: *Plane, pos_: i32, size_: i32) !void {
const height: i32 = @intCast(plane.dim_y());
var size = @max(size_, 8);
const pos: i32 = @min(height * eighths_c - size, pos_);

View file

@ -195,7 +195,7 @@ fn animate(self: *Self) bool {
else
frame;
smooth_block_at(self.plane, pos);
smooth_block_at(&self.plane, pos);
return false;
// return pos != 0;
}
@ -204,7 +204,7 @@ const eighths_l = [_][]const u8{ "█", "▉", "▊", "▋", "▌", "▍", "▎"
const eighths_r = [_][]const u8{ " ", "", "🮇", "🮈", "", "🮉", "🮊", "🮋" };
const eighths_c = eighths_l.len;
fn smooth_block_at(plane: Plane, pos: u64) void {
fn smooth_block_at(plane: *Plane, pos: u64) void {
const blk = @mod(pos, eighths_c) + 1;
const l = eighths_l[eighths_c - blk];
const r = eighths_r[eighths_c - blk];

View file

@ -3,7 +3,6 @@ const Allocator = std.mem.Allocator;
const tp = @import("thespian");
const tracy = @import("tracy");
const root = @import("root");
const egc = @import("renderer").egc;
const Plane = @import("renderer").Plane;
const style = @import("renderer").style;
@ -25,9 +24,9 @@ pub fn create(a: Allocator, parent: Plane) !Widget {
});
}
pub fn layout(_: *void, _: *Button.State(void)) Widget.Layout {
pub fn layout(_: *void, btn: *Button.State(void)) Widget.Layout {
const name = tui.get_mode();
const width = egc.chunk_width(name, 0);
const width = btn.plane.egc_chunk_width(name, 0);
const padding: usize = if (is_mini_mode()) 3 else 2;
return .{ .static = width + padding };
}

View file

@ -93,13 +93,6 @@ fn init(a: Allocator) !*Self {
const frame_time = std.time.us_per_s / conf.frame_rate;
const frame_clock = try tp.metronome.init(frame_time);
const fd_stdin = try tp.file_descriptor.init("stdin", ctx.input_fd());
// const fd_stdin = try tp.file_descriptor.init("stdin", std.os.STDIN_FILENO);
const n = ctx.stdplane();
try frame_clock.start();
try fd_stdin.wait_read();
self.* = .{
.a = a,
.config = conf,
@ -107,7 +100,7 @@ fn init(a: Allocator) !*Self {
.frame_time = frame_time,
.frame_clock = frame_clock,
.frame_clock_running = true,
.fd_stdin = fd_stdin,
.fd_stdin = undefined,
.receiver = Receiver.init(receive, self),
.mainview = undefined,
.message_filters = MessageFilter.List.init(a),
@ -120,6 +113,15 @@ fn init(a: Allocator) !*Self {
};
instance_ = self;
defer instance_ = null;
try self.rdr.run();
self.fd_stdin = try tp.file_descriptor.init("stdin", self.rdr.input_fd());
// self.fd_stdin = try tp.file_descriptor.init("stdin", std.os.STDIN_FILENO);
const n = self.rdr.stdplane();
try frame_clock.start();
try self.fd_stdin.wait_read();
self.rdr.handler_ctx = self;
self.rdr.dispatch_input = dispatch_input;
self.rdr.dispatch_mouse = dispatch_mouse;
@ -129,7 +131,7 @@ fn init(a: Allocator) !*Self {
errdefer self.deinit();
try self.listen_sigwinch();
self.mainview = try mainview.create(a, n);
try ctx.render();
try self.rdr.render();
try self.save_config();
if (tp.env.get().is("restore-session")) {
command.executeName("restore_session", .{}) catch |e| self.logger.err("restore_session", e);
@ -305,7 +307,7 @@ fn render(self: *Self, current_time: i64) void {
};
{
const frame = tracy.initZone(@src(), .{ .name = "notcurses render" });
const frame = tracy.initZone(@src(), .{ .name = renderer.log_name ++ " render" });
defer frame.deinit();
self.rdr.render() catch |e| self.logger.err("render", e);
}
@ -342,7 +344,10 @@ fn dispatch_input_fd(self: *Self, m: tp.message) error{Exit}!bool {
var err_msg: []u8 = "";
if (try m.match(.{ "fd", "stdin", "read_ready" })) {
self.fd_stdin.wait_read() catch |e| return tp.exit_error(e);
self.rdr.process_input() catch |e| return tp.exit_error(e);
self.rdr.process_input() catch |e| switch (e) {
error.WouldBlock => return true,
else => return tp.exit_error(e),
};
try self.dispatch_flush_input_event();
if (self.unrendered_input_events_count > 0 and !self.frame_clock_running)
need_render();
@ -512,18 +517,17 @@ const cmds = struct {
const l = log.logger("z stack");
defer l.deinit();
var buf: [256]u8 = undefined;
var buf_parent: [256]u8 = undefined;
var z: i32 = 0;
var n = self.rdr.stdplane();
while (n.below()) |n_| : (n = n_) {
z -= 1;
l.print("{d} {s} {s}", .{ z, n_.name(&buf), n_.parent().name(&buf_parent) });
l.print("{d} {s}", .{ z, n_.name(&buf) });
}
z = 0;
n = self.rdr.stdplane();
while (n.above()) |n_| : (n = n_) {
z += 1;
l.print("{d} {s} {s}", .{ z, n_.name(&buf), n_.parent().name(&buf_parent) });
l.print("{d} {s}", .{ z, n_.name(&buf) });
}
}