this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

test_input example working

authored by

Jeffrey C. Ollie and committed by
Tim Culverhouse
fc28d184 2dd8fe89

+57 -53
+14 -16
examples/text_input.zig
··· 18 18 foo: u8, 19 19 }; 20 20 21 - pub fn main() !void { 22 - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; 23 - defer { 24 - const deinit_status = gpa.deinit(); 25 - //fail test; can't try in defer as defer is executed after we return 26 - if (deinit_status == .leak) { 27 - log.err("memory leak", .{}); 28 - } 29 - } 30 - const alloc = gpa.allocator(); 21 + pub fn main(init: std.process.Init) !void { 22 + const io = init.io; 23 + const alloc = init.gpa; 31 24 32 25 // Initalize a tty 33 26 var buffer: [1024]u8 = undefined; 34 - var tty = try vaxis.Tty.init(&buffer); 27 + var tty = try vaxis.Tty.init(io, &buffer); 35 28 defer tty.deinit(); 36 29 37 30 // Use a buffered writer for better performance. There are a lot of writes ··· 39 32 const writer = tty.writer(); 40 33 41 34 // Initialize Vaxis 42 - var vx = try vaxis.init(alloc, .{ 35 + var vx = try vaxis.init(io, alloc, init.environ_map, .{ 43 36 .kitty_keyboard_flags = .{ .report_events = true }, 44 37 }); 45 38 defer vx.deinit(alloc, tty.writer()); ··· 48 41 .vaxis = &vx, 49 42 .tty = &tty, 50 43 }; 51 - try loop.init(); 44 + try loop.init(io); 52 45 53 46 // Start the read loop. This puts the terminal in raw mode and begins 54 47 // reading user input ··· 77 70 // queue which can serve as the primary event queue for an application 78 71 while (true) { 79 72 // nextEvent blocks until an event is in the queue 80 - const event = loop.nextEvent(); 73 + const event = try loop.nextEvent(); 81 74 log.debug("event: {}", .{event}); 82 75 // exhaustive switching ftw. Vaxis will send events if your Event 83 76 // enum has the fields for those events (ie "key_press", "winsize") ··· 94 87 } else if (key.matches('n', .{ .ctrl = true })) { 95 88 try vx.notify(tty.writer(), "vaxis", "hello from vaxis"); 96 89 loop.stop(); 97 - var child = std.process.Child.init(&.{"nvim"}, alloc); 98 - _ = try child.spawnAndWait(); 90 + var child = try std.process.spawn(io, .{ 91 + .argv = &.{"nvim"}, 92 + .stdin = .inherit, 93 + .stdout = .inherit, 94 + .stderr = .inherit, 95 + }); 96 + _ = try child.wait(io); 99 97 try loop.start(); 100 98 try vx.enterAltScreen(tty.writer()); 101 99 vx.queueRefresh();
+13 -13
src/Loop.zig
··· 66 66 } 67 67 68 68 /// returns the next available event, blocking until one is available 69 - pub fn nextEvent(self: *Self) T { 70 - return self.queue.pop(); 69 + pub fn nextEvent(self: *Self) !T { 70 + return try self.queue.pop(); 71 71 } 72 72 73 73 /// blocks until an event is available. Useful when your application is 74 74 /// operating on a poll + drain architecture (see tryEvent) 75 - pub fn pollEvent(self: *Self) void { 76 - self.queue.poll(); 75 + pub fn pollEvent(self: *Self) !void { 76 + try self.queue.poll(); 77 77 } 78 78 79 79 /// returns an event if one is available, otherwise null. Non-blocking. ··· 83 83 84 84 /// posts an event into the event queue. Will block if there is not 85 85 /// capacity for the event 86 - pub fn postEvent(self: *Self, event: T) void { 87 - self.queue.push(event); 86 + pub fn postEvent(self: *Self, event: T) !void { 87 + try self.queue.push(event); 88 88 } 89 89 90 - pub fn tryPostEvent(self: *Self, event: T) bool { 91 - return self.queue.tryPush(event); 90 + pub fn tryPostEvent(self: *Self, event: T) !bool { 91 + return try self.queue.tryPush(event); 92 92 } 93 93 94 94 pub fn winsizeCallback(ptr: *anyopaque) void { ··· 96 96 // We will be receiving winsize updates in-band 97 97 if (self.vaxis.state.in_band_resize) return; 98 98 99 - const winsize = Tty.getWinsize(self.tty.fd) catch return; 99 + const winsize = self.tty.getWinsize() catch return; 100 100 if (@hasField(Event, "winsize")) { 101 - self.postEvent(.{ .winsize = winsize }); 101 + self.postEvent(.{ .winsize = winsize }) catch {}; 102 102 } 103 103 } 104 104 ··· 123 123 }, 124 124 else => { 125 125 // get our initial winsize 126 - const winsize = try Tty.getWinsize(self.tty.fd); 126 + const winsize = try self.tty.getWinsize(); 127 127 if (@hasField(Event, "winsize")) { 128 - self.postEvent(.{ .winsize = winsize }); 128 + try self.postEvent(.{ .winsize = winsize }); 129 129 } 130 130 131 131 var parser: Parser = .{}; ··· 360 360 vx.caps.multi_cursor = true; 361 361 }, 362 362 .cap_da1 => { 363 - std.Thread.Futex.wake(&vx.query_futex, 10); 363 + std.Io.futexWake(vx.io, std.atomic.Value(u32), &vx.query_futex, 10); 364 364 vx.queries_done.store(true, .unordered); 365 365 }, 366 366 .winsize => |winsize| {
+30 -24
src/tty.zig
··· 27 27 pub var global_tty: ?Tty = null; 28 28 29 29 pub const PosixTty = struct { 30 + io: std.Io, 31 + 30 32 /// the original state of the terminal, prior to calling makeRaw 31 33 termios: posix.termios, 32 34 ··· 34 36 fd: std.Io.File, 35 37 36 38 /// File.Writer for efficient buffered writing 37 - tty_writer: std.fs.File.Writer, 39 + tty_writer: std.Io.File.Writer, 38 40 39 41 pub const SignalHandler = struct { 40 42 context: *anyopaque, ··· 43 45 44 46 /// global signal handlers 45 47 var handlers: [8]SignalHandler = undefined; 46 - var handler_mutex: std.Thread.Mutex = .{}; 48 + var handler_io: std.Io = undefined; 49 + var handler_mutex: std.Io.Mutex = .init; 47 50 var handler_idx: usize = 0; 48 51 49 52 var handler_installed: bool = false; ··· 54 57 pub fn init(io: std.Io, buffer: []u8) !PosixTty { 55 58 // Open our tty 56 59 var f = try std.Io.Dir.openFileAbsolute(io, "/dev/tty", .{ .mode = .read_write }); 57 - // const fd = try posix.open("/dev/tty", .{ .ACCMODE = .RDWR }, 0); 58 60 59 61 // Set the termios of the tty 60 62 const termios = try makeRaw(f.handle); 61 63 62 - var act = posix.Sigaction{ 63 - .handler = .{ .handler = PosixTty.handleWinch }, 64 - .mask = switch (builtin.os.tag) { 65 - .macos => 0, 66 - else => posix.sigemptyset(), 67 - }, 68 - .flags = 0, 69 - }; 70 - posix.sigaction(posix.SIG.WINCH, &act, null); 71 - handler_installed = true; 64 + if (!handler_installed) { 65 + var act = posix.Sigaction{ 66 + .handler = .{ .handler = PosixTty.handleWinch }, 67 + .mask = switch (builtin.os.tag) { 68 + .macos => 0, 69 + else => posix.sigemptyset(), 70 + }, 71 + .flags = 0, 72 + }; 73 + posix.sigaction(posix.SIG.WINCH, &act, null); 74 + handler_io = io; 75 + handler_installed = true; 76 + } 72 77 73 78 // const file = std.fs.File{ .handle = fd }; 74 79 75 80 const self: PosixTty = .{ 81 + .io = io, 76 82 .fd = f, 77 83 .termios = termios, 78 - .tty_writer = f.readerStreaming(io, &buffer), 84 + .tty_writer = f.writerStreaming(io, buffer), 79 85 }; 80 86 81 87 global_tty = self; ··· 85 91 86 92 /// release resources associated with the Tty return it to its original state 87 93 pub fn deinit(self: PosixTty) void { 88 - posix.tcsetattr(self.fd, .FLUSH, self.termios) catch |err| { 94 + posix.tcsetattr(self.fd.handle, .FLUSH, self.termios) catch |err| { 89 95 std.log.err("couldn't restore terminal: {}", .{err}); 90 96 }; 91 97 if (builtin.os.tag != .macos) // closing /dev/tty may block indefinitely on macos 92 - posix.close(self.fd); 98 + self.fd.close(self.io); 93 99 } 94 100 95 101 /// Resets the signal handler to it's default ··· 112 118 } 113 119 114 120 pub fn read(self: *const PosixTty, buf: []u8) !usize { 115 - return posix.read(self.fd, buf); 121 + return try self.fd.readStreaming(self.io, &.{buf}); 116 122 } 117 123 118 124 /// Install a signal handler for winsize. A maximum of 8 handlers may be 119 125 /// installed 120 126 pub fn notifyWinsize(handler: SignalHandler) !void { 121 - handler_mutex.lock(); 122 - defer handler_mutex.unlock(); 127 + try handler_mutex.lock(handler_io); 128 + defer handler_mutex.unlock(handler_io); 123 129 if (handler_idx == handlers.len) return error.OutOfMemory; 124 130 handlers[handler_idx] = handler; 125 131 handler_idx += 1; 126 132 } 127 133 128 - fn handleWinch(_: c_int) callconv(.c) void { 129 - handler_mutex.lock(); 130 - defer handler_mutex.unlock(); 134 + fn handleWinch(_: std.posix.SIG) callconv(.c) void { 135 + handler_mutex.lock(handler_io) catch @panic("unable to lock SIGWINCH handlers"); 136 + defer handler_mutex.unlock(handler_io); 131 137 var i: usize = 0; 132 138 while (i < handler_idx) : (i += 1) { 133 139 const handler = handlers[i]; ··· 167 173 } 168 174 169 175 /// Get the window size from the kernel 170 - pub fn getWinsize(fd: posix.fd_t) !Winsize { 176 + pub fn getWinsize(self: *PosixTty) !Winsize { 171 177 var winsize = posix.winsize{ 172 178 .row = 0, 173 179 .col = 0, ··· 175 181 .ypixel = 0, 176 182 }; 177 183 178 - const err = posix.system.ioctl(fd, posix.T.IOCGWINSZ, @intFromPtr(&winsize)); 184 + const err = posix.system.ioctl(self.fd.handle, posix.T.IOCGWINSZ, @intFromPtr(&winsize)); 179 185 if (posix.errno(err) == .SUCCESS) 180 186 return Winsize{ 181 187 .rows = winsize.row,