Skip to content

usage g completion-init zsh breaks default completion with _files #692

Description

@dhanak

After installing generic completion for usage scripts, zsh completion complains:

$ emacs <TAB>
(eval):1: no matches found: *:globbed-files

Below is Codex's analysis of the issue. It might be overcomplicating things quite a bit, but the crux is valid: if I remove emulate -L zsh from the completion-init script, the problem goes away.

The bug is here:

_usage_default_complete() {
    emulate -L zsh
    ...
    _files
}

emulate -L zsh resets shell options for the function. That is dangerous inside zsh completion functions because the completion system relies on a particular option environment when helpers like _files / _path_files run.

The fallback:

_files

is then running under the wrong local option state, so zsh eventually evaluates an internal file-pattern tag such as:

*:globbed-files

as a real glob. With nomatch active, this becomes:

no matches found: *:globbed-files

Minimal patch

Change:

emulate -L zsh

to:

emulate -L zsh
setopt localoptions nonomatch extendedglob

or more defensively:

emulate -L zsh -o extendedglob
setopt localoptions nonomatch

Better patch

Avoid forcing emulation around the fallback:

_usage_default_complete() {
    emulate -L zsh -o extendedglob
    setopt localoptions nonomatch

    local cmd cmdpath
    ...
    # Not a usage shebang script — fall back to file completion
    _files
}

Even better design

Do not replace the global default completer with a wrapper that calls _files directly:

compdef _usage_default_complete -default-

That is broad and fragile. It intercepts completion for every command without a specific completion.

A safer fallback would be:

_default

instead of:

_files

So the end becomes:

# Not a usage shebang script — fall back to normal default completion
_default

But then you must avoid infinite recursion, because this function itself is installed as -default-. So the robust fix is more involved: it should save the previous default completion function before replacing it, then call that previous handler as fallback.

Practical local workaround

Edit the generated script locally and patch the top:

_usage_default_complete() {
    emulate -L zsh -o extendedglob
    setopt localoptions nonomatch

Then restart zsh or reload the file.

The core issue is not globbed-files; that is a normal zsh completion tag. The problem is the generated completion wrapper changes the option environment and then delegates to _files.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions