Something still isn't quite right. With the fix, I don't get the error message anymore, for sure. But:
$ source <(usage g completion-init zsh)
$ emacs --<TAB>[completion inserts "\*" here]
$ source <(usage g completion-init zsh | sed -e 's/emulate -L zsh//')
$ emacs --<TAB>[bell, nothing is inserted]
I asked the AI again:
That confirms the diagnosis: emulate -L zsh is clobbering the completion system’s expected option state.
The * insertion is a second symptom of the same thing. Adding nonomatch only suppresses the error; it lets the bad fallback proceed, so _files treats the internal * pattern as a literal candidate and inserts it.
Better fix
Do not call _files after emulate -L zsh.
Instead, preserve the caller’s completion options around the generated code, or only use emulate in the branch that calls usage.
Try this structure:
_usage_default_complete() {
local cmd cmdpath
cmd="${words[1]}"
if [[ "$cmd" == */* ]]; then
cmdpath="$cmd"
elif (( ${+commands[$cmd]} )); then
cmdpath="${commands[$cmd]}"
fi
if [[ -n "$cmdpath" && -f "$cmdpath" ]]; then
local first
if IFS= read -r first < "$cmdpath" 2>/dev/null && [[ "$first" == "#!"*"usage"* ]]; then
if (( ${+commands[usage]} )); then
emulate -L zsh
local -a values=() descs=() inserts=()
local needs_menu=0 line
while IFS= read -r line; do
local -a parts=("${(@ps:\t:)line}")
values+=("${parts[1]}")
descs+=("${parts[2]}")
inserts+=("${parts[3]}")
[[ "${parts[3]}" == "'"* ]] && needs_menu=1
done < <(command usage complete-word --shell zsh -f "$cmdpath" --cword=$((CURRENT - 1)) -- "${(Q)words[@]}")
(( needs_menu )) && compstate[insert]=menu
if (( ${#inserts[@]} )); then
local -a _usage_display=()
local _usage_i _usage_max=0 _usage_v _usage_pad
for _usage_v in "${values[@]}"; do
(( ${#_usage_v} > _usage_max )) && _usage_max=${#_usage_v}
done
for ((_usage_i=1; _usage_i<=${#values[@]}; _usage_i++)); do
if [[ -n "${descs[_usage_i]}" ]]; then
_usage_pad=$(( _usage_max - ${#values[_usage_i]} ))
_usage_display+=("${values[_usage_i]}${(l:_usage_pad:: :)} -- ${descs[_usage_i]}")
else
_usage_display+=("${values[_usage_i]}")
fi
done
compadd -l -d _usage_display -U -Q -S '' -a inserts
fi
return $?
fi
fi
fi
_files
}
Smaller patch
Move:
from the top of the function to inside this branch:
if (( ${+commands[usage]} )); then
emulate -L zsh
...
fi
That way _files runs in the original completion environment.
Why deleting it works
Completion functions are already called in a special context. _files expects that context. Top-level emulate -L zsh resets options too broadly, so fallback completion breaks.
setopt nonomatch masks the exception but leaves the completion semantics wrong, hence literal * insertion.
Originally posted by @dhanak in #692
Originally posted by @dhanak in #692