Preserve ZSH options in the shell integration (#2950)

This fixes the #2847. There were two problems:
1. Documentation made it easy to use the bash example as a template for
calling other integrations
2. f the ZSH integration script is called the same way as for bash, it
would clobber the options

This PR fixes both. Now the ZSH script can be simply called with
`source`.

Here is why the options were clobbered, and how the method of calling
affected it:

The `-L` flag (local scope) ensures that the emulation mode only applies
to the current function scope. When the function ends, the shell reverts
to its previous state. When called outside of a function, the flags
persist even after the script execution ends.

The recommended way of calling the ZSH integration included `autoload
-Uz` that created a function with the integration script as its body.
When called directly, the assumptions about being in the function body
broke.

This PR moves a lot of code into a function, so it's best to review with
whitespace ignored in the diff.
This commit is contained in:
Mitchell Hashimoto
2024-12-12 16:44:56 -08:00
committed by GitHub
3 changed files with 67 additions and 47 deletions

View File

@ -286,13 +286,16 @@ if [ -n "${GHOSTTY_RESOURCES_DIR}" ]; then
fi
```
For details see <a href="https://github.com/ghostty-org/ghostty/blob/main/src/shell-integration/README.md">shell-integration/README.md</a>.
Each shell integration's installation instructions are documented inline:
| Shell | Integration |
| ------ | ---------------------------------------------------------------------------------------------- |
| -------- | ---------------------------------------------------------------------------------------------- |
| `bash` | `${GHOSTTY_RESOURCES_DIR}/shell-integration/bash/ghostty.bash` |
| `fish` | `${GHOSTTY_RESOURCES_DIR}/shell-integration/fish/vendor_conf.d/ghostty-shell-integration.fish` |
| `zsh` | `${GHOSTTY_RESOURCES_DIR}/shell-integration/zsh/ghostty-integration` |
| `elvish` | `${GHOSTTY_RESOURCES_DIR}/shell-integration/elvish/lib/ghostty-integration.elv` |
### Terminfo

View File

@ -24,6 +24,13 @@ must be explicitly enabled (`shell-integration = bash`).
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
```
### Elvish
For [Elvish](https://elv.sh), `$GHOSTTY_RESOURCES_DIR/src/shell-integration`
@ -59,3 +66,9 @@ For `zsh`, Ghostty sets `ZDOTDIR` so that it loads our configuration
from the `zsh` directory. The existing `ZDOTDIR` is retained so that
after loading the Ghostty shell integration the normal Zsh loading
sequence occurs.
```bash
if [[ -n $GHOSTTY_RESOURCES_DIR ]]; then
"$GHOSTTY_RESOURCES_DIR"/shell-integration/zsh/ghostty-integration
fi
```

View File

@ -25,9 +25,7 @@
# Ghostty in all shells should add the following lines to their .zshrc:
#
# if [[ -n $GHOSTTY_RESOURCES_DIR ]]; then
# autoload -Uz -- "$GHOSTTY_RESOURCES_DIR"/shell-integration/zsh/ghostty-integration
# ghostty-integration
# unfunction ghostty-integration
# "$GHOSTTY_RESOURCES_DIR"/shell-integration/zsh/ghostty-integration
# fi
#
# Implementation note: We can assume that alias expansion is disabled in this
@ -35,6 +33,9 @@
# builtins with `builtin` to avoid accidentally invoking user-defined functions.
# We avoid `function` reserved word as an additional defensive measure.
# Note that updating options with `builtin emulate -L zsh` affects the global options
# if it's called outside of a function. So nearly all code has to be in functions.
_entrypoint() {
builtin emulate -L zsh -o no_warn_create_global -o no_aliases
[[ -o interactive ]] || builtin return 0 # non-interactive shell
@ -78,6 +79,7 @@ typeset -gi _ghostty_fd
# the integration.
builtin typeset -ag precmd_functions
precmd_functions+=(_ghostty_deferred_init)
}
_ghostty_deferred_init() {
builtin emulate -L zsh -o no_warn_create_global -o no_aliases
@ -310,3 +312,5 @@ _ghostty_deferred_init() {
# to unfunction themselves when invoked. Unfunctioning is done by calling code.
builtin unfunction _ghostty_deferred_init
}
_entrypoint