feat(termio): port pty, child command spawning, shell integration
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`)
This commit is contained in:
1 parent
6792799fbe
commit
59bc84fde0
21 files changed
+7120
-28
No files matched your search
@@ -0,0 +1,117 @@
|
||||
# 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+.
|
||||
Reference in new issue
Block a user