From 8239f09d9d76a3f16afae631270bbeefd130f177 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 6 Jul 2023 18:04:12 -0700 Subject: [PATCH] allow configuring shell integration injection --- src/config.zig | 33 ++++++++++++++++++++++++++++++-- src/termio/Exec.zig | 10 +++++++++- src/termio/shell_integration.zig | 7 ++++++- 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/config.zig b/src/config.zig index a54c5e062..8b5bc0918 100644 --- a/src/config.zig +++ b/src/config.zig @@ -197,10 +197,32 @@ pub const Config = struct { /// Additional configuration files to read. @"config-file": RepeatableString = .{}, - // Confirms that a surface should be closed before closing it. This defaults - // to true. If set to false, surfaces will close without any confirmation. + /// Confirms that a surface should be closed before closing it. This defaults + /// to true. If set to false, surfaces will close without any confirmation. @"confirm-close-surface": bool = true, + /// Whether to enable shell integration auto-injection or not. Shell + /// integration greatly enhances the terminal experience by enabling + /// a number of features: + /// + /// * Working directory reporting so new tabs, splits inherit the + /// previous terminal's working directory. + /// * Prompt marking that enables the "scroll_to_prompt" keybinding. + /// * If you're sitting at a prompt, closing a terminal will not ask + /// for confirmation. + /// * Resizing the window with a complex prompt usually paints much + /// better. + /// + /// Allowable values are: + /// + /// * "none" - Do not do any automatic injection. You can still manually + /// configure your shell to enable the integration. + /// * "auto" - Detect the shell based on the filename. + /// * "fish", "zsh" - Use this specific shell injection scheme. + /// + /// The default value is "auto". + @"shell-integration": ShellIntegration = .auto, + /// This is set by the CLI parser for deinit. _arena: ?ArenaAllocator = null, @@ -1209,6 +1231,13 @@ pub const Keybinds = struct { } }; +pub const ShellIntegration = enum { + none, + auto, + fish, + zsh, +}; + // Wasm API. pub const Wasm = if (!builtin.target.isWasm()) struct {} else struct { const wasm = @import("os/wasm.zig"); diff --git a/src/termio/Exec.zig b/src/termio/Exec.zig index a70967284..cd1f2ba04 100644 --- a/src/termio/Exec.zig +++ b/src/termio/Exec.zig @@ -603,11 +603,19 @@ const Subprocess = struct { // Setup our shell integration, if we can. const shell_integrated: ?shell_integration.Shell = shell: { + const force: ?shell_integration.Shell = switch (opts.full_config.@"shell-integration") { + .none => break :shell null, + .auto => null, + .fish => .fish, + .zsh => .zsh, + }; + const dir = resources_dir orelse break :shell null; break :shell try shell_integration.setup( dir, final_path, &env, + force, ); }; if (shell_integrated) |shell| { @@ -615,7 +623,7 @@ const Subprocess = struct { "shell integration automatically injected shell={}", .{shell}, ); - } else { + } else if (opts.full_config.@"shell-integration" != .none) { log.warn("shell could not be detected, no automatic shell integration will be injected", .{}); } diff --git a/src/termio/shell_integration.zig b/src/termio/shell_integration.zig index 15cf9a9d6..6f8fe3220 100644 --- a/src/termio/shell_integration.zig +++ b/src/termio/shell_integration.zig @@ -17,8 +17,13 @@ pub fn setup( resource_dir: []const u8, command_path: []const u8, env: *EnvMap, + force_shell: ?Shell, ) !?Shell { - const exe = std.fs.path.basename(command_path); + const exe = if (force_shell) |shell| switch (shell) { + .fish => "/fish", + .zsh => "/zsh", + } else std.fs.path.basename(command_path); + if (std.mem.eql(u8, "fish", exe)) { try setupFish(resource_dir, env); return .fish;