refactor: lots and lots of writergate changes

This commit is contained in:
CJ van den Berg 2025-09-24 22:30:18 +02:00
parent 96e8100373
commit e6b39c274c
Signed by: neurocyte
GPG key ID: 8EB1E1BB660E3FB9
19 changed files with 437 additions and 382 deletions

View file

@ -181,7 +181,7 @@ pub fn putstr(self: *Plane, text: []const u8) !usize {
var result: usize = 0;
const height = self.window.height;
const width = self.window.width;
var iter = self.window.screen.unicode.graphemeIterator(text);
var iter = self.window.unicode.graphemeIterator(text);
while (iter.next()) |grapheme| {
const s = grapheme.bytes(text);
if (std.mem.eql(u8, s, "\n")) {
@ -443,7 +443,7 @@ pub fn egc_length(self: *const Plane, egcs: []const u8, colcount: *c_int, abs_co
colcount.* = @intCast(tab_width - (abs_col % tab_width));
return 1;
}
var iter = self.window.screen.unicode.graphemeIterator(egcs);
var iter = self.window.unicode.graphemeIterator(egcs);
const grapheme = iter.next() orelse {
colcount.* = 1;
return 1;
@ -470,7 +470,7 @@ pub fn egc_chunk_width(self: *const Plane, chunk_: []const u8, abs_col_: usize,
}
pub fn egc_last(self: *const Plane, egcs: []const u8) []const u8 {
var iter = self.window.screen.unicode.graphemeIterator(egcs);
var iter = self.window.unicode.graphemeIterator(egcs);
var last: []const u8 = egcs[0..0];
while (iter.next()) |grapheme| last = grapheme.bytes(egcs);
return last;

View file

@ -1,5 +1,6 @@
const vaxis = @import("vaxis");
const Io = @import("std").Io;
const meta = @import("std").meta;
const unicode = @import("std").unicode;
const FormatOptions = @import("std").fmt.FormatOptions;
@ -88,12 +89,12 @@ pub const KeyEvent = struct {
return self.modifiers & ~mod.caps_lock;
}
pub fn format(self: @This(), comptime _: []const u8, _: FormatOptions, writer: anytype) !void {
pub fn format(self: @This(), writer: anytype) !void {
const mods = self.mods_no_shifts();
return if (self.event > 0)
writer.print("{}:{}{}", .{ event_fmt(self.event), mod_fmt(mods), key_fmt(self.key) })
writer.print("{f}:{f}{f}", .{ event_fmt(self.event), mod_fmt(mods), key_fmt(self.key) })
else
writer.print("{}{}", .{ mod_fmt(mods), key_fmt(self.key) });
writer.print("{f}{f}", .{ mod_fmt(mods), key_fmt(self.key) });
}
pub fn from_key(keypress: Key) @This() {
@ -335,8 +336,8 @@ pub const utils = struct {
pub fn key_event_short_fmt(ke: KeyEvent) struct {
ke: KeyEvent,
pub fn format(self: @This(), comptime _: []const u8, _: FormatOptions, writer: anytype) !void {
return writer.print("{}{}", .{ mod_short_fmt(self.ke.modifiers), key_short_fmt(self.ke.key) });
pub fn format(self: @This(), writer: anytype) Io.Writer.Error!void {
return writer.print("{f}{f}", .{ mod_short_fmt(self.ke.modifiers), key_short_fmt(self.ke.key) });
}
} {
return .{ .ke = ke };
@ -344,7 +345,7 @@ pub fn key_event_short_fmt(ke: KeyEvent) struct {
pub fn event_fmt(evt: Event) struct {
event: Event,
pub fn format(self: @This(), comptime _: []const u8, _: FormatOptions, writer: anytype) !void {
pub fn format(self: @This(), writer: anytype) Io.Writer.Error!void {
return switch (self.event) {
event.press => writer.writeAll("press"),
event.repeat => writer.writeAll("repeat"),
@ -358,7 +359,7 @@ pub fn event_fmt(evt: Event) struct {
pub fn event_short_fmt(evt: Event) struct {
event: Event,
pub fn format(self: @This(), comptime _: []const u8, _: FormatOptions, writer: anytype) !void {
pub fn format(self: @This(), writer: anytype) Io.Writer.Error!void {
return switch (self.event) {
event.press => writer.writeAll("P"),
event.repeat => writer.writeAll("RP"),
@ -372,11 +373,11 @@ pub fn event_short_fmt(evt: Event) struct {
pub fn key_fmt(key_: Key) struct {
key: Key,
pub fn format(self: @This(), comptime _: []const u8, _: FormatOptions, writer: anytype) !void {
pub fn format(self: @This(), writer: anytype) Io.Writer.Error!void {
var key_string = utils.key_id_string(self.key);
var buf: [6]u8 = undefined;
if (key_string.len == 0) {
const bytes = try ucs32_to_utf8(&[_]u32{self.key}, &buf);
const bytes = ucs32_to_utf8(&[_]u32{self.key}, &buf) catch return error.WriteFailed;
key_string = buf[0..bytes];
}
try writer.writeAll(key_string);
@ -387,7 +388,7 @@ pub fn key_fmt(key_: Key) struct {
pub fn key_short_fmt(key_: Key) struct {
key: Key,
pub fn format(self: @This(), comptime _: []const u8, _: FormatOptions, writer: anytype) !void {
pub fn format(self: @This(), writer: anytype) Io.Writer.Error!void {
var key_string = utils.key_id_string_short(self.key);
var buf: [6]u8 = undefined;
if (key_string.len == 0) {
@ -402,7 +403,7 @@ pub fn key_short_fmt(key_: Key) struct {
pub fn mod_fmt(mods: Mods) struct {
modifiers: Mods,
pub fn format(self: @This(), comptime _: []const u8, _: FormatOptions, writer: anytype) !void {
pub fn format(self: @This(), writer: anytype) Io.Writer.Error!void {
const modset: ModSet = @bitCast(self.modifiers);
if (modset.super) try writer.writeAll("super+");
if (modset.ctrl) try writer.writeAll("ctrl+");
@ -415,7 +416,7 @@ pub fn mod_fmt(mods: Mods) struct {
pub fn mod_short_fmt(mods: Mods) struct {
modifiers: Mods,
pub fn format(self: @This(), comptime _: []const u8, _: FormatOptions, writer: anytype) !void {
pub fn format(self: @This(), writer: anytype) Io.Writer.Error!void {
const modset: ModSet = @bitCast(self.modifiers);
if (modset.super) try writer.writeAll("Super-");
if (modset.ctrl) try writer.writeAll("C-");

View file

@ -22,15 +22,16 @@ allocator: std.mem.Allocator,
tty: vaxis.Tty,
vx: vaxis.Vaxis,
tty_buffer: []u8,
no_alternate: bool,
event_buffer: std.ArrayList(u8),
input_buffer: std.ArrayList(u8),
event_buffer: std.Io.Writer.Allocating,
input_buffer: std.Io.Writer.Allocating,
mods: vaxis.Key.Modifiers = .{},
queries_done: bool,
bracketed_paste: bool = false,
bracketed_paste_buffer: std.ArrayList(u8),
bracketed_paste_buffer: std.Io.Writer.Allocating,
handler_ctx: *anyopaque,
dispatch_input: ?*const fn (ctx: *anyopaque, cbor_msg: []const u8) void = null,
@ -61,6 +62,7 @@ pub const Error = error{
BadArrayAllocExtract,
InvalidMapType,
InvalidUnion,
WriteFailed,
} || std.Thread.SpawnError;
pub fn init(allocator: std.mem.Allocator, handler_ctx: *anyopaque, no_alternate: bool, _: *const fn (ctx: *anyopaque) void) Error!Self {
@ -74,13 +76,15 @@ pub fn init(allocator: std.mem.Allocator, handler_ctx: *anyopaque, no_alternate:
},
.system_clipboard_allocator = allocator,
};
const tty_buffer = try allocator.alloc(u8, 4096);
return .{
.allocator = allocator,
.tty = vaxis.Tty.init() catch return error.TtyInitError,
.tty = vaxis.Tty.init(tty_buffer) catch return error.TtyInitError,
.tty_buffer = tty_buffer,
.vx = try vaxis.init(allocator, opts),
.no_alternate = no_alternate,
.event_buffer = std.ArrayList(u8).init(allocator),
.input_buffer = std.ArrayList(u8).init(allocator),
.event_buffer = .init(allocator),
.input_buffer = .init(allocator),
.bracketed_paste_buffer = std.ArrayList(u8).init(allocator),
.handler_ctx = handler_ctx,
.logger = log.logger(log_name),
@ -94,6 +98,7 @@ pub fn deinit(self: *Self) void {
self.loop.stop();
self.vx.deinit(self.allocator, self.tty.anyWriter());
self.tty.deinit();
self.allocator.free(self.tty_buffer);
self.bracketed_paste_buffer.deinit();
self.input_buffer.deinit();
self.event_buffer.deinit();
@ -204,9 +209,8 @@ pub fn run(self: *Self) Error!void {
pub fn render(self: *Self) !void {
if (in_panic.load(.acquire)) return;
var bufferedWriter = self.tty.bufferedWriter();
try self.vx.render(bufferedWriter.writer().any());
try bufferedWriter.flush();
try self.vx.render(&self.tty.writer.interface);
try self.tty.writer.interface.flush();
}
pub fn sigwinch(self: *Self) !void {
@ -214,7 +218,7 @@ pub fn sigwinch(self: *Self) !void {
try self.resize(try vaxis.Tty.getWinsize(self.input_fd_blocking()));
}
fn resize(self: *Self, ws: vaxis.Winsize) error{ TtyWriteError, OutOfMemory }!void {
fn resize(self: *Self, ws: vaxis.Winsize) error{ TtyWriteError, OutOfMemory, WriteFailed }!void {
self.vx.resize(self.allocator, self.tty.anyWriter(), ws) catch return error.TtyWriteError;
self.vx.queueRefresh();
if (self.dispatch_event) |f| f(self.handler_ctx, try self.fmtmsg(.{"resize"}));
@ -394,25 +398,26 @@ pub fn process_renderer_event(self: *Self, msg: []const u8) Error!void {
}
}
fn fmtmsg(self: *Self, value: anytype) std.ArrayList(u8).Writer.Error![]const u8 {
fn fmtmsg(self: *Self, value: anytype) std.Io.Writer.Error![]const u8 {
self.event_buffer.clearRetainingCapacity();
try cbor.writeValue(self.event_buffer.writer(), value);
return self.event_buffer.items;
try cbor.writeValue(&self.event_buffer.writer, value);
return self.event_buffer.written();
}
fn handle_bracketed_paste_input(self: *Self, cbor_msg: []const u8) !bool {
var keypress: input.Key = undefined;
var egc_: input.Key = undefined;
var mods: usize = undefined;
const writer = &self.bracketed_paste_buffer.writer;
if (try cbor.match(cbor_msg, .{ "I", cbor.number, cbor.extract(&keypress), cbor.extract(&egc_), cbor.string, cbor.extract(&mods) })) {
switch (keypress) {
106 => if (mods == 4) try self.bracketed_paste_buffer.appendSlice("\n") else try self.bracketed_paste_buffer.appendSlice("j"),
input.key.enter => try self.bracketed_paste_buffer.appendSlice("\n"),
input.key.tab => try self.bracketed_paste_buffer.appendSlice("\t"),
106 => if (mods == 4) try writer.writeAll("\n") else try writer.writeAll("j"),
input.key.enter => try writer.writeAll("\n"),
input.key.tab => try writer.writeAll("\t"),
else => if (!input.is_non_input_key(keypress)) {
var buf: [6]u8 = undefined;
const bytes = try input.ucs32_to_utf8(&[_]u32{egc_}, &buf);
try self.bracketed_paste_buffer.appendSlice(buf[0..bytes]);
try writer.writeAll(buf[0..bytes]);
} else {
var buf: [6]u8 = undefined;
const bytes = try input.ucs32_to_utf8(&[_]u32{egc_}, &buf);
@ -431,16 +436,16 @@ fn handle_bracketed_paste_start(self: *Self) !void {
fn handle_bracketed_paste_end(self: *Self) !void {
defer {
self.bracketed_paste_buffer.clearAndFree();
self.bracketed_paste_buffer.clearRetainingCapacity();
self.bracketed_paste = false;
}
if (!self.bracketed_paste) return;
if (self.dispatch_event) |f| f(self.handler_ctx, try self.fmtmsg(.{ "system_clipboard", self.bracketed_paste_buffer.items }));
if (self.dispatch_event) |f| f(self.handler_ctx, try self.fmtmsg(.{ "system_clipboard", self.bracketed_paste_buffer.written() }));
}
fn handle_bracketed_paste_error(self: *Self, e: Error) !void {
self.logger.err("bracketed paste", e);
self.bracketed_paste_buffer.clearAndFree();
self.bracketed_paste_buffer.clearRetainingCapacity();
self.bracketed_paste = false;
return e;
}