Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any plugin or script using bashcompinit & complete to define completion won't work after sourcing antigen #736

Open
segevfiner opened this issue Apr 4, 2022 · 4 comments · May be fixed by #737

Comments

@segevfiner
Copy link

Description

The google-cloud-sdk adds the following snippet to the end of your .zshrc:

# The next line updates PATH for the Google Cloud SDK.
if [ -f '/Users/segevfiner/google-cloud-sdk/path.zsh.inc' ]; then . '/Users/segevfiner/google-cloud-sdk/path.zsh.inc'; fi

# The next line enables shell command completion for gcloud.
if [ -f '/Users/segevfiner/google-cloud-sdk/completion.zsh.inc' ]; then . '/Users/segevfiner/google-cloud-sdk/completion.zsh.inc'; fi

Their completion script is using bashcompinit and complete to define completions. This translates to a bunch of compdef calls like this:

compdef '_bash_complete -o nospace -o default -F _python_argcomplete' gcloud

If this happens after antigen apply, the compdef is ignored:

compdef () {}

Which is weird...? Why?

Moving it between sourcing antigen and antigen apply causes antigen to defer the compdef call using:

compdef () { __deferred_compdefs=($__deferred_compdefs "$*") }

Which causes it to save it as a single string inside the array, losing the quoting and the fact that it has multiple arguments, and then the subsequent compdef call here doesn't work:

compdef "$cdef"

As it needs to call compdef with two arguments but calls it with one.

# Wrong (Caused by the code deferring compdef)
compdef '_bash_complete -o nospace -o default -F _python_argcomplete gcloud'

# Correct
compdef '_bash_complete -o nospace -o default -F _python_argcomplete' gcloud

In general, I think this might happen with any compdef call at all, as they all use more than one argument.

Also note that nvm generates the following:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

And its completion script calls compinit, which antigen isn't trying to defer/skip, which will then undo the effect of deferring compdef (nvm-sh/nvm/bash_completion:89-95) getting the completion to be defined correctly but hurting shell startup performance due to multiple compinit invocations. Making it not call compinit by commenting that out, causes the same kind of issue with its own defined completions not loading as happens with the google-cloud-sdk, although nvm has completion available in the Zsh default completion and an oh-my-zsh plugin with completions that will end up getting used instead.

You can load such completions before sourcing antigen, which will make it call compdef before antigen tries to defer it, which seems to work, but there might be a reason for this attempted deferral of compdef calls.

I'm not really sure how to resolve this as Zsh doesn't support nested arrays or something obvious to store an array of such multiple argument commands...

P.S. As antigen doesn't appear to be maintained, this is unlikely to be resolved, any recommendations for an alternative to antigen (With good oh-my-zsh plugins support, good performance, and being actually maintained), workaround, fix to apply locally, or anything else?

Steps to reproduce

Minimal steps to reproduce this behavior. Example:

1 - Use any `.zshrc` that calls `compdef` between sourcing antigen and `antigen apply`. (`antigen reset` if needed, not sure when antigen invalidates its cache)
2 - Check `$_comps[command]` (e.g. `$_comps[gcloud]`) to see if the completion is defined properly.

Expected behavior:

- Deferred `compdef` completion to be defined correctly.

Software version

  • antigen version
    Antigen v2.2.3 (ff391b5)
    Revision date: 2018-01-02 13:19:57 +0100
  • zsh --version zsh 5.8 (x86_64-apple-darwin21.0)
  • uname -a Darwin Segevs-MacBook-Pro.local 21.4.0 Darwin Kernel Version 21.4.0: Fri Mar 18 00:46:32 PDT 2022; root:xnu-8020.101.4~15/RELEASE_ARM64_T6000 arm64

Configuration

.zshrc
source /opt/homebrew/share/antigen/antigen.zsh

FPATH="$(brew --prefix)/share/zsh/site-functions:${FPATH}"
LESS=-FR

antigen use oh-my-zsh

antigen bundle git
antigen bundle fzf
antigen bundle zsh-users/zsh-completions
antigen bundle zsh-users/zsh-autosuggestions
antigen bundle zsh-users/zsh-syntax-highlighting

eval "$(starship init zsh)"

export ZSH_HIGHLIGHT_HIGHLIGHTERS=(main brackets)

# The next line updates PATH for the Google Cloud SDK.
if [ -f '/Users/segevfiner/google-cloud-sdk/path.zsh.inc' ]; then . '/Users/segevfiner/google-cloud-sdk/path.zsh.inc'; fi

# The next line enables shell command completion for gcloud.
if [ -f '/Users/segevfiner/google-cloud-sdk/completion.zsh.inc' ]; then . '/Users/segevfiner/google-cloud-sdk/completion.zsh.inc'; fi

antigen apply

More information

image 😢

@segevfiner
Copy link
Author

So maybe using some Zsh specific magic:

$ A=("Foo Bar" Qux)
$ B=${(@qq)A}
$ printf "%s\n" ${(Q)${(z)B}}
Foo Bar
Qux

segevfiner added a commit to segevfiner/antigen that referenced this issue Apr 5, 2022
@mr-narender
Copy link

+1

@donhector
Copy link

donhector commented Apr 20, 2023

Terraform completion is another one impacted by this bug.

~/.zshrc

[...]

autoload -U +X bashcompinit && bashcompinit
complete -o nospace -C "$(which terraform)" terraform

complete above internally runs:

compdef '_bash_complete -o nospace -C /path/to/terraform' terraform

When running the complete command manually on my shell, completions get loaded, but not when they are loaded from ~/.zshrc

@mblakesley
Copy link

+1

I'm a shell noob, but here's how I would describe it:

Antigen causes complete command to not work in .zshrc file.

complete works when run in zsh, but not when I put it in my .zshrc file. There, it runs, gives a 0 exit status, but then autocompletion doesn't work. Examples: AWS CLI v2 autocomplete, Terraform autocomplete.

The interwebs suggested various problems with autoload, bashcompinit, etc, but none of those resolved my problem. In the end, it was simple: the AWS complete command works when I put it in my .bashrc. So then I went back to my .zshrc and kept removing things until AWS complete worked. It only worked after removing Antigen itself.

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 a pull request may close this issue.

4 participants