Ports the parts of Ghostty's IO layer that don't depend on the terminal: - pty.zig: pty pair, window size, mode, child-side setsid/TIOCSCTTY; master is CLOEXEC with IUTF8 set - Command.zig: fork/execvpe with Ghostty's exact child setup (stdio dup2, best-effort chdir, rlimit restore, os/runtime pre-exec hooks, cgroup handling) and exit status decoding - shell_integration.zig for bash/zsh/fish/elvish/nushell plus feature flags; scripts copied verbatim to resources/shell-integration/ - terminfo generator for xterm-ghostty, byte-identical to Zig's encode output (golden file produced with the real Zig code) This crate opts into unsafe_code = "deny" (fork/exec need it) with allow + SAFETY comments on minimal items. Integration left: config-derived option types are local stand-ins; cgroup D-Bus scope creation is a closure hook; Exec/Termio/Thread/ stream_handler wait for ghostty-terminal. Pty now closes both fds on drop (Zig never auto-closed the slave) - to re-check when wiring Exec. Test Plan: - cargo test -p ghostty-termio (52 tests, incl. real pty spawn test expecting "hi\r\n31 97\r\n" from `echo hi; stty size`)
118 lines
4.3 KiB
Markdown
118 lines
4.3 KiB
Markdown
# Shell Integration Code
|
|
|
|
This is the shell-specific shell-integration code that is
|
|
used for the shell-integration feature set that Ghostty
|
|
supports.
|
|
|
|
This README is meant as developer documentation and not as
|
|
user documentation. For user documentation, see the main
|
|
README or [ghostty.org](https://ghostty.org/docs)
|
|
|
|
## Implementation Details
|
|
|
|
### Bash
|
|
|
|
Automatic [Bash](https://www.gnu.org/software/bash/) shell integration works by
|
|
starting Bash in POSIX mode and using the `ENV` environment variable to load
|
|
our integration script (`bash/ghostty.bash`). This prevents Bash from loading
|
|
its normal startup files, which becomes our script's responsibility (along with
|
|
disabling POSIX mode).
|
|
|
|
Bash shell integration can also be sourced manually from `bash/ghostty.bash`.
|
|
This also works for older versions of Bash.
|
|
|
|
```bash
|
|
# Ghostty shell integration for Bash. This must be at the top of your bashrc!
|
|
if [ -n "${GHOSTTY_RESOURCES_DIR}" ]; then
|
|
builtin source "${GHOSTTY_RESOURCES_DIR}/shell-integration/bash/ghostty.bash"
|
|
fi
|
|
```
|
|
|
|
> [!NOTE]
|
|
>
|
|
> The version of Bash distributed with macOS (`/bin/bash`) does not support
|
|
> automatic shell integration. You'll need to manually source the shell
|
|
> integration script (as shown above). You can also install a standard
|
|
> version of Bash from Homebrew or elsewhere and set it as your shell.
|
|
|
|
### 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` every time after shell startup or
|
|
autostart integration in `$XDG_CONFIG_HOME/elvish/rc.elv`,
|
|
which will run the integration routines.
|
|
|
|
If you decide to autostart `ghostty-integration` with `rc.elv`, you should
|
|
detect whether the terminal is Ghostty or not. To do this, add this to the end
|
|
of your `rc.elv` file:
|
|
|
|
```elvish
|
|
if (eq $E:TERM "xterm-ghostty") {
|
|
try { use ghostty-integration } catch { }
|
|
}
|
|
```
|
|
|
|
The [Elvish](https://elv.sh) shell integration is supported by
|
|
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.
|
|
If you experience issues with the Elvish shell integration, I welcome
|
|
any contributions to fix them. Thank you!
|
|
|
|
### Fish
|
|
|
|
For [Fish](https://fishshell.com/), Ghostty prepends to the
|
|
`XDG_DATA_DIRS` directory. Fish automatically loads configuration
|
|
files in `<XDG_DATA_DIR>/fish/vendor_conf.d/*.fish` on startup,
|
|
allowing us to automatically integrate with the shell. For details
|
|
on the Fish startup process, see the
|
|
[Fish documentation](https://fishshell.com/docs/current/language.html).
|
|
|
|
### Nushell
|
|
|
|
For [Nushell](https://www.nushell.sh/), Ghostty prepends to the
|
|
`XDG_DATA_DIRS` directory, making the `ghostty` module available through
|
|
Nushell's vendor autoload mechanism. Ghostty then automatically imports
|
|
the module using the `-e "use ghostty *"` flag when starting Nushell.
|
|
|
|
Nushell provides many shell features itself, such as `title` and `cursor`,
|
|
so our integration focuses on Ghostty-specific features like `sudo`,
|
|
`ssh-env`, and `ssh-terminfo`.
|
|
|
|
The shell integration is automatically enabled when running Nushell in Ghostty,
|
|
but you can also load it manually is shell integration is disabled:
|
|
|
|
```nushell
|
|
source $GHOSTTY_RESOURCES_DIR/shell-integration/nushell/vendor/autoload/ghostty.nu
|
|
use ghostty *
|
|
```
|
|
|
|
### Zsh
|
|
|
|
Automatic [Zsh](https://www.zsh.org/) integration works by temporarily setting
|
|
`ZDOTDIR` to our `zsh` directory. An existing `ZDOTDIR` environment variable
|
|
value will be retained and restored after our shell integration scripts are
|
|
run.
|
|
|
|
However, if `ZDOTDIR` is set in a system-wide file like `/etc/zshenv`, it will
|
|
override Ghostty's `ZDOTDIR` value, preventing the shell integration from being
|
|
loaded. In this case, the shell integration needs to be loaded manually.
|
|
|
|
To load the Zsh shell integration manually:
|
|
|
|
```zsh
|
|
if [[ -n $GHOSTTY_RESOURCES_DIR ]]; then
|
|
source "$GHOSTTY_RESOURCES_DIR"/shell-integration/zsh/ghostty-integration
|
|
fi
|
|
```
|
|
|
|
Shell integration requires Zsh 5.1+.
|