feat(shell-integration): add automatic integration for Elvish

Fish automatic integration taken as an example.
Just like fish, Elvish checks `XDG_DATA_DIRS` for its modules.
Thus, Fish integration in zig is reused, and integration in
Elvish now removes `GHOSTTY_FISH_XDG_DIR` environment variable
on launch.
This commit is contained in:
ilk
2024-05-16 23:59:02 +03:00
committed by Mitchell Hashimoto
parent 1032cdb68f
commit 1fa830cc73
4 changed files with 39 additions and 5 deletions

View File

@ -3414,6 +3414,7 @@ pub const ShellIntegration = enum {
bash, bash,
fish, fish,
zsh, zsh,
elvish,
}; };
/// Shell integration features /// Shell integration features

View File

@ -19,9 +19,20 @@ its normal startup files, which becomes our script's responsibility (along with
disabling POSIX mode). disabling POSIX mode).
Bash shell integration can also be sourced manually from `bash/ghostty.bash`. Bash shell integration can also be sourced manually from `bash/ghostty.bash`.
### Elvish ### Elvish
For [Elvish](https://elv.sh), `$GHOSTTY_RESOURCES_DIR/src/shell-integration`
contains an `./elvish/lib/ghostty-integration.elv` file.
Elvish, on startup, searches for paths defined in `XDG_DATA_DIRS`
variable for `./elvish/lib/*.elv` files and imports them. They are thus
made available for use as modules by way of `use <filename>`.
Ghostty launches Elvish, passing the environment with `XDG_DATA_DIRS`prepended
with `$GHOSTTY_RESOURCES_DIR/src/shell-integration`. It contains
`./elvish/lib/ghostty-integration.elv`. The user can then import it
by `use ghostty-integration`, which will run the integration routines.
The [Elvish](https://elv.sh) shell integration is supported by The [Elvish](https://elv.sh) shell integration is supported by
the community and is not officially supported by Ghostty. We distribute the community and is not officially supported by Ghostty. We distribute
it for ease of access and use but do not provide support for it. it for ease of access and use but do not provide support for it.
@ -43,3 +54,4 @@ For `zsh`, Ghostty sets `ZDOTDIR` so that it loads our configuration
from the `zsh` directory. The existing `ZDOTDIR` is retained so that from the `zsh` directory. The existing `ZDOTDIR` is retained so that
after loading the Ghostty shell integration the normal Zsh loading after loading the Ghostty shell integration the normal Zsh loading
sequence occurs. sequence occurs.

View File

@ -1,6 +1,6 @@
{ {
fn restore-xdg-dirs { fn restore-xdg-dirs {
var integration-dir = $E:GHOSTTY_FISH_XDG_DIR var integration-dir = $E:GHOSTTY_INTEGRATION_DIR
var xdg-dirs = [(str:split ':' $E:XDG_DATA_DIRS)] var xdg-dirs = [(str:split ':' $E:XDG_DATA_DIRS)]
var len = (count $xdg-dirs) var len = (count $xdg-dirs)
@ -27,9 +27,9 @@
} else { } else {
set-env XDG_DATA_DIRS (str:join ':' $xdg-dirs) set-env XDG_DATA_DIRS (str:join ':' $xdg-dirs)
} }
unset-env GHOSTTY_FISH_XDG_DIR unset-env GHOSTTY_INTEGRATION_DIR
} }
if (and (has-env GHOSTTY_FISH_XDG_DIR) (has-env XDG_DATA_DIRS)) { if (and (has-env GHOSTTY_INTEGRATION_DIR) (has-env XDG_DATA_DIRS)) {
restore-xdg-dirs restore-xdg-dirs
} }
} }
@ -117,4 +117,3 @@
edit:add-var sudo~ $sudo-with-terminfo~ edit:add-var sudo~ $sudo-with-terminfo~
} }
} }

View File

@ -12,6 +12,7 @@ pub const Shell = enum {
bash, bash,
fish, fish,
zsh, zsh,
elvish,
}; };
/// The result of setting up a shell integration. /// The result of setting up a shell integration.
@ -47,6 +48,7 @@ pub fn setup(
.bash => "bash", .bash => "bash",
.fish => "fish", .fish => "fish",
.zsh => "zsh", .zsh => "zsh",
.elvish => "elvish",
} else exe: { } else exe: {
// The command can include arguments. Look for the first space // The command can include arguments. Look for the first space
// and use the basename of the first part as the command's exe. // and use the basename of the first part as the command's exe.
@ -76,6 +78,14 @@ pub fn setup(
}; };
} }
if (std.mem.eql(u8, "elvish", exe)) {
try setupElvish(alloc_arena, resource_dir, env);
break :shell .{
.shell = .elvish,
.command = command,
};
}
if (std.mem.eql(u8, "zsh", exe)) { if (std.mem.eql(u8, "zsh", exe)) {
try setupZsh(resource_dir, env); try setupZsh(resource_dir, env);
break :shell .{ break :shell .{
@ -452,6 +462,18 @@ fn setupFish(
} }
} }
/// Setup the Elvish automatic shell integration.
/// This reuses integration primitives of Fish, as Elvish also
/// loads config in XDG_DATA_DIRS (except it imports
/// "./elvish/lib/*.elv" files).
fn setupElvish(
alloc_arena: Allocator,
resource_dir: []const u8,
env: *EnvMap,
) !void {
try setupFish(alloc_arena, resource_dir, env);
}
/// Setup the zsh automatic shell integration. This works by setting /// Setup the zsh automatic shell integration. This works by setting
/// ZDOTDIR to our resources dir so that zsh will load our config. This /// ZDOTDIR to our resources dir so that zsh will load our config. This
/// config then loads the true user config. /// config then loads the true user config.