widgets(terminal): use buffered reader in parser

Use a buffered reader so we can inspect the read state. We need this to
know if we have a finished read on a printable byte
This commit is contained in:
Tim Culverhouse 2024-06-10 15:03:48 -05:00
parent 9f2af4d5ee
commit b688732f56
2 changed files with 15 additions and 8 deletions

View file

@ -4,6 +4,7 @@ const Parser = @This();
const std = @import("std");
const Reader = std.io.AnyReader;
const ansi = @import("ansi.zig");
const BufferedReader = std.io.BufferedReader(4096, std.io.AnyReader);
/// A terminal event
const Event = union(enum) {
@ -21,7 +22,8 @@ buf: std.ArrayList(u8),
/// a leftover byte from a ground event
pending_byte: ?u8 = null,
pub fn parseReader(self: *Parser, reader: Reader) !Event {
pub fn parseReader(self: *Parser, buffered: *BufferedReader) !Event {
const reader = buffered.reader().any();
self.buf.clearRetainingCapacity();
while (true) {
const b = if (self.pending_byte) |p| p else try reader.readByte();
@ -56,21 +58,27 @@ pub fn parseReader(self: *Parser, reader: Reader) !Event {
=> return .{ .c0 = @enumFromInt(b) },
else => {
try self.buf.append(b);
return self.parseGround(reader);
return self.parseGround(buffered);
},
}
}
}
inline fn parseGround(self: *Parser, reader: Reader) !Event {
inline fn parseGround(self: *Parser, reader: *BufferedReader) !Event {
var buf: [1]u8 = undefined;
while (true) {
const b = try reader.readByte();
if (reader.start == reader.end) return .{ .print = self.buf.items };
const n = try reader.read(&buf);
if (n == 0) return error.EOF;
const b = buf[0];
switch (b) {
0x00...0x1f => {
self.pending_byte = b;
return .{ .print = self.buf.items };
},
else => try self.buf.append(b),
else => {
try self.buf.append(b);
},
}
}
}

View file

@ -251,11 +251,10 @@ fn run(self: *Terminal) !void {
defer parser.buf.deinit();
// Use our anyReader to make a buffered reader, then get *that* any reader
var buffered = std.io.bufferedReader(self.anyReader());
const reader = buffered.reader().any();
var reader = std.io.bufferedReader(self.anyReader());
while (!self.should_quit) {
const event = try parser.parseReader(reader);
const event = try parser.parseReader(&reader);
self.back_mutex.lock();
defer self.back_mutex.unlock();