Skip to content

fix(zsh): which is a builtin in zsh mode, so Esc Esc stops erroring - #181

Merged
LESdylan merged 1 commit into
developfrom
fix/zsh-which-builtin
Oct 18, 2026
Merged

LESdylan merged 1 commit into
developfrom
fix/zsh-which-builtin

Conversation

@LESdylan

Copy link
Copy Markdown
Member

oh-my-zsh's sudo widget runs builtin which -a on every Esc Esc (with $EDITOR set). hellish had no such builtin: every toggle printed builtin: which: not a shell builtin, and vim f with $EDITOR = a second vim on $PATH became sudo vim f instead of sudo -e f.

  • which [-ap] name... = zsh's whence -c; diffed against zsh 5.8.1 on 20 invocations — identical except the error prefix.
  • zsh mode only: a separate table consulted by builtin_func() under zsh_mode(), so bash scripts keep /usr/bin/which (type which, command -v which unchanged). builtin_func() now takes the shell state; every caller had it.
  • omz_sudo_widget_test.py: new second-vim case + no "not a shell builtin" anywhere — 2 failed before, 11 ok after. Golden 5363/5363; zsh_builtins, zle, plugin_corpus pass. wiki/builtins regenerated (also adds the missing bind).

🤖 Generated with Claude Code

oh-my-zsh's sudo widget runs `builtin which -a "$cmd"` on every Esc Esc
once $EDITOR is set, and hellish had no `which` builtin: each toggle
printed "builtin: which: not a shell builtin" over the prompt, and an
editor reached only through that check (`vim f` with EDITOR set to a
second vim on $PATH) became `sudo vim f` instead of `sudo -e f`.

`which [-ap] name...` is zsh's (whence -c): alias, reserved word,
function, builtin, then the command; -a lists every match, -p paths
only; "NAME not found" on stdout and status 1, as zsh. Diffed against
zsh 5.8.1 on 20 invocations: identical apart from the error prefix.

It resolves in zsh mode only. `which` is also /usr/bin/which, and a
bash script's `which`, `type which` and `command -v which` must keep
meaning that one, so it sits in a separate table that builtin_func()
consults only under zsh_mode(). builtin_func() now takes the shell
state for that; every caller already had it, and the compiler found
them all. declare -f's body trimming moves to func_text_trimmed() so
`which` prints a function with the same text.

Caveats in the code: functions print as written rather than deparsed;
the reserved words are the POSIX set. tests/omz_sudo_widget_test.py adds
the second-vim case and fails on "not a shell builtin" anywhere: 2
failed before, 11 ok after. Golden suite 5363/5363; zsh_builtins,
zle and plugin_corpus tests pass. wiki/builtins regenerated (it also
picks up `bind`, which was missing).
@LESdylan
LESdylan merged commit 98de69e into develop Oct 18, 2026
35 checks passed
@LESdylan
LESdylan deleted the fix/zsh-which-builtin branch October 18, 2026 02:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant