mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 07:46:12 +03:00
Fix shell-integration-features being ignored with manual shell integration (#5048)
## Descriptions The code was short-circuiting the shell integration setup when `shell-integration = none`, which prevented the feature environment variables from being set. These environment variables are needed even for manual shell integration to work properly. ## Changes - Extracted feature environment variables setup into a separate `setup_features` function - Modified the shell integration initialization to ensure features are set up even when `shell-integration = none` <img width="1126" alt="image" src="https://github.com/user-attachments/assets/ceeb33f5-26ee-4a3b-a6d5-eed57848c96c" /> Fixes https://github.com/ghostty-org/ghostty/issues/5046
This commit is contained in:
@ -1670,7 +1670,9 @@ keybind: Keybinds = .{},
|
||||
/// The default value is `detect`.
|
||||
@"shell-integration": ShellIntegration = .detect,
|
||||
|
||||
/// Shell integration features to enable if shell integration itself is enabled.
|
||||
/// Shell integration features to enable. These require our shell integration
|
||||
/// to be loaded, either automatically via shell-integration or manually.
|
||||
///
|
||||
/// The format of this is a list of features to enable separated by commas. If
|
||||
/// you prefix a feature with `no-` then it is disabled. If you omit a feature,
|
||||
/// its default value is used, so you must explicitly disable features you don't
|
||||
|
@ -875,7 +875,11 @@ const Subprocess = struct {
|
||||
};
|
||||
|
||||
const force: ?shell_integration.Shell = switch (cfg.shell_integration) {
|
||||
.none => break :shell .{ null, default_shell_command },
|
||||
.none => {
|
||||
// Even if shell integration is none, we still want to set up the feature env vars
|
||||
try shell_integration.setupFeatures(&env, cfg.shell_integration_features);
|
||||
break :shell .{ null, default_shell_command };
|
||||
},
|
||||
.detect => null,
|
||||
.bash => .bash,
|
||||
.elvish => .elvish,
|
||||
|
@ -58,7 +58,21 @@ pub fn setup(
|
||||
break :exe std.fs.path.basename(command[0..idx]);
|
||||
};
|
||||
|
||||
const result: ShellIntegration = shell: {
|
||||
const result = try setupShell(alloc_arena, resource_dir, command, env, exe);
|
||||
|
||||
// Setup our feature env vars
|
||||
try setupFeatures(env, features);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn setupShell(
|
||||
alloc_arena: Allocator,
|
||||
resource_dir: []const u8,
|
||||
command: []const u8,
|
||||
env: *EnvMap,
|
||||
exe: []const u8,
|
||||
) !?ShellIntegration {
|
||||
if (std.mem.eql(u8, "bash", exe)) {
|
||||
// Apple distributes their own patched version of Bash 3.2
|
||||
// on macOS that disables the ENV-based POSIX startup path.
|
||||
@ -80,7 +94,7 @@ pub fn setup(
|
||||
resource_dir,
|
||||
env,
|
||||
) orelse return null;
|
||||
break :shell .{
|
||||
return .{
|
||||
.shell = .bash,
|
||||
.command = new_command,
|
||||
};
|
||||
@ -88,7 +102,7 @@ pub fn setup(
|
||||
|
||||
if (std.mem.eql(u8, "elvish", exe)) {
|
||||
try setupXdgDataDirs(alloc_arena, resource_dir, env);
|
||||
break :shell .{
|
||||
return .{
|
||||
.shell = .elvish,
|
||||
.command = try alloc_arena.dupe(u8, command),
|
||||
};
|
||||
@ -96,7 +110,7 @@ pub fn setup(
|
||||
|
||||
if (std.mem.eql(u8, "fish", exe)) {
|
||||
try setupXdgDataDirs(alloc_arena, resource_dir, env);
|
||||
break :shell .{
|
||||
return .{
|
||||
.shell = .fish,
|
||||
.command = try alloc_arena.dupe(u8, command),
|
||||
};
|
||||
@ -104,21 +118,13 @@ pub fn setup(
|
||||
|
||||
if (std.mem.eql(u8, "zsh", exe)) {
|
||||
try setupZsh(resource_dir, env);
|
||||
break :shell .{
|
||||
return .{
|
||||
.shell = .zsh,
|
||||
.command = try alloc_arena.dupe(u8, command),
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
// Setup our feature env vars
|
||||
if (!features.cursor) try env.put("GHOSTTY_SHELL_INTEGRATION_NO_CURSOR", "1");
|
||||
if (!features.sudo) try env.put("GHOSTTY_SHELL_INTEGRATION_NO_SUDO", "1");
|
||||
if (!features.title) try env.put("GHOSTTY_SHELL_INTEGRATION_NO_TITLE", "1");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
test "force shell" {
|
||||
@ -138,6 +144,58 @@ test "force shell" {
|
||||
}
|
||||
}
|
||||
|
||||
/// Setup shell integration feature environment variables without
|
||||
/// performing full shell integration setup.
|
||||
pub fn setupFeatures(
|
||||
env: *EnvMap,
|
||||
features: config.ShellIntegrationFeatures,
|
||||
) !void {
|
||||
if (!features.cursor) try env.put("GHOSTTY_SHELL_INTEGRATION_NO_CURSOR", "1");
|
||||
if (!features.sudo) try env.put("GHOSTTY_SHELL_INTEGRATION_NO_SUDO", "1");
|
||||
if (!features.title) try env.put("GHOSTTY_SHELL_INTEGRATION_NO_TITLE", "1");
|
||||
}
|
||||
|
||||
test "setup features" {
|
||||
const testing = std.testing;
|
||||
|
||||
var arena = ArenaAllocator.init(testing.allocator);
|
||||
defer arena.deinit();
|
||||
const alloc = arena.allocator();
|
||||
|
||||
// Test: all features enabled (no environment variables should be set)
|
||||
{
|
||||
var env = EnvMap.init(alloc);
|
||||
defer env.deinit();
|
||||
|
||||
try setupFeatures(&env, .{ .cursor = true, .sudo = true, .title = true });
|
||||
try testing.expect(env.get("GHOSTTY_SHELL_INTEGRATION_NO_CURSOR") == null);
|
||||
try testing.expect(env.get("GHOSTTY_SHELL_INTEGRATION_NO_SUDO") == null);
|
||||
try testing.expect(env.get("GHOSTTY_SHELL_INTEGRATION_NO_TITLE") == null);
|
||||
}
|
||||
|
||||
// Test: all features disabled
|
||||
{
|
||||
var env = EnvMap.init(alloc);
|
||||
defer env.deinit();
|
||||
|
||||
try setupFeatures(&env, .{ .cursor = false, .sudo = false, .title = false });
|
||||
try testing.expectEqualStrings("1", env.get("GHOSTTY_SHELL_INTEGRATION_NO_CURSOR").?);
|
||||
try testing.expectEqualStrings("1", env.get("GHOSTTY_SHELL_INTEGRATION_NO_SUDO").?);
|
||||
try testing.expectEqualStrings("1", env.get("GHOSTTY_SHELL_INTEGRATION_NO_TITLE").?);
|
||||
}
|
||||
|
||||
// Test: mixed features
|
||||
{
|
||||
var env = EnvMap.init(alloc);
|
||||
defer env.deinit();
|
||||
|
||||
try setupFeatures(&env, .{ .cursor = false, .sudo = true, .title = false });
|
||||
try testing.expectEqualStrings("1", env.get("GHOSTTY_SHELL_INTEGRATION_NO_CURSOR").?);
|
||||
try testing.expect(env.get("GHOSTTY_SHELL_INTEGRATION_NO_SUDO") == null);
|
||||
try testing.expectEqualStrings("1", env.get("GHOSTTY_SHELL_INTEGRATION_NO_TITLE").?);
|
||||
}
|
||||
}
|
||||
|
||||
/// Setup the bash automatic shell integration. This works by
|
||||
/// starting bash in POSIX mode and using the ENV environment
|
||||
/// variable to load our bash integration script. This prevents
|
||||
|
Reference in New Issue
Block a user