From 3625e1e58e4617e741668c1543763b0f4bdc2487 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 15 Jul 2024 09:55:31 -0700 Subject: [PATCH] termio: take reader as option --- src/Surface.zig | 20 ++++++++++++ src/termio.zig | 1 + src/termio/Options.zig | 3 ++ src/termio/Termio.zig | 32 +++++++------------- src/termio/reader.zig | 69 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 21 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index 208a1e258..00dc9ce55 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -426,6 +426,25 @@ pub fn init( }; // Start our IO implementation + var io_exec = try termio.Exec.init(alloc, .{ + .command = config.command, + .shell_integration = config.@"shell-integration", + .shell_integration_features = config.@"shell-integration-features", + .working_directory = config.@"working-directory", + .resources_dir = main.state.resources_dir, + .term = config.term, + + // Get the cgroup if we're on linux and have the decl. I'd love + // to change this from a decl to a surface options struct because + // then we can do memory management better (don't need to retain + // the string around). + .linux_cgroup = if (comptime builtin.os.tag == .linux and + @hasDecl(apprt.runtime.Surface, "cgroup")) + rt_surface.cgroup() + else + Command.linux_cgroup_default, + }); + errdefer io_exec.deinit(); var io_writer = try termio.Writer.initMailbox(alloc); errdefer io_writer.deinit(alloc); try termio.Termio.init(&self.io, alloc, .{ @@ -434,6 +453,7 @@ pub fn init( .padding = padding, .full_config = config, .config = try termio.Termio.DerivedConfig.init(alloc, config), + .reader = .{ .exec = io_exec }, .writer = io_writer, .resources_dir = main.state.resources_dir, .renderer_state = &self.renderer_state, diff --git a/src/termio.zig b/src/termio.zig index 4fce4df18..a780786ae 100644 --- a/src/termio.zig +++ b/src/termio.zig @@ -13,6 +13,7 @@ pub const Termio = @import("termio/Termio.zig"); pub const Thread = @import("termio/Thread.zig"); pub const DerivedConfig = Termio.DerivedConfig; pub const Mailbox = writer.Mailbox; +pub const Reader = reader.Reader; pub const StreamHandler = stream_handler.StreamHandler; pub const Writer = writer.Writer; diff --git a/src/termio/Options.zig b/src/termio/Options.zig index 2cb636d60..7e97f7dfd 100644 --- a/src/termio/Options.zig +++ b/src/termio/Options.zig @@ -25,6 +25,9 @@ full_config: *const Config, /// The derived configuration for this termio implementation. config: termio.Termio.DerivedConfig, +/// The reader for the terminal. +reader: termio.Reader, + /// The writer for the terminal. This is how messages are delivered. /// If you're using termio.Thread this MUST be "mailbox". writer: termio.Writer, diff --git a/src/termio/Termio.zig b/src/termio/Termio.zig index 8a0a7051c..02e8f28d4 100644 --- a/src/termio/Termio.zig +++ b/src/termio/Termio.zig @@ -33,8 +33,8 @@ const log = std.log.scoped(.io_exec); /// Allocator alloc: Allocator, -/// This is the pty fd created for the subcommand. -subprocess: termio.Exec, +/// This is the implementation responsible for io. +reader: termio.Reader, /// The derived configuration for this termio implementation. config: DerivedConfig, @@ -169,18 +169,8 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void { term.screen.cursor.cursor_style = opts.config.cursor_style; // Setup our reader. - // TODO: for manual, we need to set the terminal width/height - var subprocess = try termio.Exec.init(alloc, .{ - .command = opts.full_config.command, - .shell_integration = opts.full_config.@"shell-integration", - .shell_integration_features = opts.full_config.@"shell-integration-features", - .working_directory = opts.full_config.@"working-directory", - .resources_dir = opts.resources_dir, - .term = opts.config.term, - .linux_cgroup = opts.linux_cgroup, - }); - errdefer subprocess.deinit(); - subprocess.initTerminal(&term); + var reader = opts.reader; + reader.initTerminal(&term); // Setup our terminal size in pixels for certain requests. const screen_size = opts.screen_size.subPadding(opts.padding); @@ -220,13 +210,13 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void { self.* = .{ .alloc = alloc, .terminal = term, - .subprocess = subprocess, .config = opts.config, .renderer_state = opts.renderer_state, .renderer_wakeup = opts.renderer_wakeup, .renderer_mailbox = opts.renderer_mailbox, .surface_mailbox = opts.surface_mailbox, .grid_size = opts.grid_size, + .reader = opts.reader, .writer = opts.writer, .terminal_stream = .{ .handler = handler, @@ -242,7 +232,7 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void { } pub fn deinit(self: *Termio) void { - self.subprocess.deinit(); + self.reader.deinit(); self.terminal.deinit(self.alloc); self.config.deinit(); self.writer.deinit(self.alloc); @@ -272,11 +262,11 @@ pub fn threadEnter(self: *Termio, thread: *termio.Thread, data: *ThreadData) !vo }; // Setup our reader - try self.subprocess.threadEnter(alloc, self, data); + try self.reader.threadEnter(alloc, self, data); } pub fn threadExit(self: *Termio, data: *ThreadData) void { - self.subprocess.threadExit(data); + self.reader.threadExit(data); } /// Send a message using the writer. Depending on the writer type in @@ -310,7 +300,7 @@ pub inline fn queueWrite( data: []const u8, linefeed: bool, ) !void { - try self.subprocess.queueWrite(self.alloc, td, data, linefeed); + try self.reader.queueWrite(self.alloc, td, data, linefeed); } /// Update the configuration. @@ -373,7 +363,7 @@ pub fn resize( ) !void { // Update the size of our pty. const padded_size = screen_size.subPadding(padding); - try self.subprocess.resize(grid_size, padded_size); + try self.reader.resize(grid_size, padded_size); // Update our cached grid size self.grid_size = grid_size; @@ -476,7 +466,7 @@ pub fn childExitedAbnormally(self: *Termio, exit_code: u32, runtime_ms: u64) !vo self.renderer_state.mutex.lock(); defer self.renderer_state.mutex.unlock(); const t = self.renderer_state.terminal; - try self.subprocess.childExitedAbnormally(self.alloc, t, exit_code, runtime_ms); + try self.reader.childExitedAbnormally(self.alloc, t, exit_code, runtime_ms); } /// Process output from the pty. This is the manual API that users can diff --git a/src/termio/reader.zig b/src/termio/reader.zig index add25d8b0..de7536078 100644 --- a/src/termio/reader.zig +++ b/src/termio/reader.zig @@ -9,6 +9,7 @@ const configpkg = @import("../config.zig"); const internal_os = @import("../os/main.zig"); const renderer = @import("../renderer.zig"); const shell_integration = @import("shell_integration.zig"); +const terminal = @import("../terminal/main.zig"); const termio = @import("../termio.zig"); const Command = @import("../Command.zig"); const SegmentedPool = @import("../segmented_pool.zig").SegmentedPool; @@ -44,6 +45,74 @@ pub const Reader = union(Kind) { .exec => |*exec| exec.deinit(), } } + + pub fn initTerminal(self: *Reader, t: *terminal.Terminal) void { + switch (self.*) { + .manual => {}, + .exec => |*exec| exec.initTerminal(t), + } + } + + pub fn threadEnter( + self: *Reader, + alloc: Allocator, + io: *termio.Termio, + td: *termio.Termio.ThreadData, + ) !void { + switch (self.*) { + .manual => {}, + .exec => |*exec| try exec.threadEnter(alloc, io, td), + } + } + + pub fn threadExit(self: *Reader, td: *termio.Termio.ThreadData) void { + switch (self.*) { + .manual => {}, + .exec => |*exec| exec.threadExit(td), + } + } + + pub fn resize( + self: *Reader, + grid_size: renderer.GridSize, + screen_size: renderer.ScreenSize, + ) !void { + switch (self.*) { + .manual => {}, + .exec => |*exec| try exec.resize(grid_size, screen_size), + } + } + + pub fn queueWrite( + self: *Reader, + alloc: Allocator, + td: *termio.Termio.ThreadData, + data: []const u8, + linefeed: bool, + ) !void { + switch (self.*) { + .manual => {}, + .exec => |*exec| try exec.queueWrite(alloc, td, data, linefeed), + } + } + + pub fn childExitedAbnormally( + self: *Reader, + gpa: Allocator, + t: *terminal.Terminal, + exit_code: u32, + runtime_ms: u64, + ) !void { + switch (self.*) { + .manual => {}, + .exec => |*exec| try exec.childExitedAbnormally( + gpa, + t, + exit_code, + runtime_ms, + ), + } + } }; /// Termio thread data. See termio.ThreadData for docs.