tty: use simple os.read loop instead of xev

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
This commit is contained in:
Tim Culverhouse 2024-01-17 22:34:40 -06:00
parent b9564b7db8
commit 48362a307c
2 changed files with 24 additions and 54 deletions

View file

@ -15,7 +15,14 @@ pub fn main() !void {
var tty = try Tty.init(); var tty = try Tty.init();
defer tty.deinit(); defer tty.deinit();
try tty.run(); const pipe = try std.os.pipe();
// run our tty read loop in it's own thread
const read_thread = try std.Thread.spawn(.{}, Tty.run, .{ &tty, pipe[0] });
try read_thread.setName("tty");
std.time.sleep(100_000_000_0);
_ = try std.os.write(pipe[1], "q");
read_thread.join();
try stdout.print("Run `zig build test` to run the tests.\n", .{}); try stdout.print("Run `zig build test` to run the tests.\n", .{});

View file

@ -12,33 +12,17 @@ termios: os.termios,
/// The file descriptor we are using for I/O /// The file descriptor we are using for I/O
fd: os.fd_t, fd: os.fd_t,
/// Stream attached to our fd
stream: xev.Stream,
/// event loop
loop: xev.Loop,
read_buffer: [1024]u8 = undefined,
/// initializes a Tty instance by opening /dev/tty and "making it raw" /// initializes a Tty instance by opening /dev/tty and "making it raw"
pub fn init() !Tty { pub fn init() !Tty {
// Open our tty // Open our tty
const fd = try os.open("/dev/tty", os.system.O.RDWR, 0); const fd = try os.open("/dev/tty", os.system.O.RDWR, 0);
// Initialize the stream
const stream = xev.Stream.initFd(fd);
// Initialize event loop
const loop = try xev.Loop.init(.{});
// Set the termios of the tty // Set the termios of the tty
const termios = try makeRaw(fd); const termios = try makeRaw(fd);
return Tty{ return Tty{
.fd = fd, .fd = fd,
.stream = stream,
.termios = termios, .termios = termios,
.loop = loop,
}; };
} }
@ -48,47 +32,26 @@ pub fn deinit(self: *Tty) void {
log.err("couldn't restore terminal: {}", .{err}); log.err("couldn't restore terminal: {}", .{err});
}; };
os.close(self.fd); os.close(self.fd);
self.stream.deinit();
self.loop.deinit();
} }
/// read input from the tty /// read input from the tty
pub fn run(self: *Tty) !void { pub fn run(self: *Tty, quit: os.fd_t) !void {
var c_stream: xev.Completion = undefined; defer os.close(quit);
var buf: [1024]u8 = undefined;
// Initialize our read event var pollfds: [2]std.os.pollfd = .{
self.stream.read( .{ .fd = self.fd, .events = std.os.POLL.IN, .revents = undefined },
&self.loop, .{ .fd = quit, .events = std.os.POLL.IN, .revents = undefined },
&c_stream,
.{ .slice = self.read_buffer[0..] },
Tty,
self,
readCallback,
);
try self.loop.run(.until_done);
}
fn readCallback(
ud: ?*Tty,
loop: *xev.Loop,
c: *xev.Completion,
stream: xev.Stream,
buf: xev.ReadBuffer,
r: xev.ReadError!usize,
) xev.CallbackAction {
_ = stream; // autofix
_ = c; // autofix
_ = loop; // autofix
const tty = ud.?;
_ = tty; // autofix
const n = r catch |err| {
// Log the error and shutdown
log.err("read error: {}", .{err});
return .disarm;
}; };
log.info("{s}\r", .{buf.slice[0..n]}); while (true) {
return .rearm; _ = try std.os.poll(&pollfds, -1);
if (pollfds[1].revents & std.os.POLL.IN != 0) {
log.info("read thread got quit signal", .{});
return;
}
const n = try os.read(self.fd, &buf);
log.err("{s}", .{buf[0..n]});
}
} }
/// makeRaw enters the raw state for the terminal. /// makeRaw enters the raw state for the terminal.