termio: take reader as option

This commit is contained in:
Mitchell Hashimoto
2024-07-15 09:55:31 -07:00
parent 4a4b9f2411
commit 3625e1e58e
5 changed files with 104 additions and 21 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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.