tools

various tools I have been using throughout the years
Log | Files | Refs | README | LICENSE

command.zig (2478B)


      1 const signals = @import("signals.zig");
      2 const std = @import("std");
      3 const terminal = @import("terminal.zig");
      4 
      5 pub const Command = enum {
      6     Pause,
      7     Quit,
      8     Reset,
      9 };
     10 
     11 pub const Poller = struct {
     12     stdin_fd: std.posix.fd_t,
     13     signals_fd: std.posix.fd_t,
     14     terminal: ?terminal.Terminal,
     15 
     16     pub fn init(allocator: std.mem.Allocator) !Poller {
     17         _ = allocator;
     18         const opt_terminal = blk: {
     19             break :blk terminal.Terminal.init() catch |err| {
     20                 std.log.debug("failed to init terminal: {any}", .{err});
     21                 break :blk null;
     22             };
     23         };
     24         errdefer {
     25             if (opt_terminal) |terminal_| {
     26                 terminal_.deinit();
     27             }
     28         }
     29 
     30         const signals_file = try signals.open();
     31         const signals_fd = signals_file.handle;
     32 
     33         return Poller{
     34             .terminal = opt_terminal,
     35             .stdin_fd = std.Io.File.stdin().handle,
     36             .signals_fd = signals_fd,
     37         };
     38     }
     39 
     40     pub fn interactive(self: *Poller) bool {
     41         return self.terminal != null;
     42     }
     43 
     44     pub fn deinit(self: *Poller) void {
     45         if (self.terminal) |terminal_| terminal_.deinit();
     46     }
     47 
     48     pub fn pollTimeout(self: *Poller, nanoseconds: u64) !?Command {
     49         var fds = [2]std.posix.pollfd{
     50             .{ .fd = self.stdin_fd, .events = std.posix.POLL.IN, .revents = 0 },
     51             .{ .fd = self.signals_fd, .events = std.posix.POLL.IN, .revents = 0 },
     52         };
     53 
     54         const timeout_ms = @as(i32, @intCast(@divTrunc(nanoseconds, std.time.ns_per_ms)));
     55         const n = try std.posix.poll(&fds, timeout_ms);
     56         if (n == 0) return null;
     57 
     58         if (fds[0].revents & std.posix.POLL.IN != 0) {
     59             var buf: [1]u8 = undefined;
     60             const bytes_read = try std.posix.read(self.stdin_fd, &buf);
     61             if (bytes_read > 0) {
     62                 switch (buf[0]) {
     63                     'p' => return Command.Pause,
     64                     'q' => return Command.Quit,
     65                     'r' => return Command.Reset,
     66                     else => {},
     67                 }
     68             }
     69         }
     70 
     71         if (fds[1].revents & std.posix.POLL.IN != 0) {
     72             const signo = try signals.readSignal(self.signals_fd);
     73             switch (signo) {
     74                 std.posix.SIG.USR1 => return Command.Pause,
     75                 std.posix.SIG.USR2 => return Command.Reset,
     76                 else => unreachable,
     77             }
     78         }
     79 
     80         return null;
     81     }
     82 };