Skip to content
New issue

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

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

Already on GitHub? # to your account

zsh completion doesn't seem to work with zinit #330

Closed
5 of 10 tasks
Gerrit-K opened this issue Jan 2, 2024 · 8 comments
Closed
5 of 10 tasks

zsh completion doesn't seem to work with zinit #330

Gerrit-K opened this issue Jan 2, 2024 · 8 comments
Assignees

Comments

@Gerrit-K
Copy link
Contributor

Gerrit-K commented Jan 2, 2024

Check list

  • I have read through the README
  • I have the latest version of forgit
  • I have searched through the existing issues

Environment info

  • OS
    • Linux
    • Mac OS X
    • Windows
    • Others:
  • Shell
    • bash
    • zsh (installed via Homebrew)
    • fish

Problem / Steps to reproduce

  • Installed zsh (5.9) via Homebrew

  • Installed fzf and forgit using zinit

    simplified zinit config
    zi wait'0a' lucid from'gh-r' pick'/dev/null' for \
      sbin'fzf' id-as'fzf-bin' junegunn/fzf
    
    zi wait'0a' lucid for \
     completions \
        wfxr/forgit
  • Try out completions

    • Only files and directories are completed, which appears to be the fallback if there are no other completions (e.g. no branch names, no cli flags etc.)
  • Try sourceing git-forgit.zsh results in _default:compcall:12: can only be called from completion function, which is likely caused by running _git directly in line 13 of the script.

I'm by far not an expert when it comes to zsh completions, but I noticed there are no _git-* completion functions, but also no git-* commands on my system. Everything is handled by git [command] and the _git completion function. Maybe the forgit completions don't account for that?

@carlfriedrich
Copy link
Collaborator

git-forgit should be in your PATH, isn't that the case?

@Gerrit-K
Copy link
Contributor Author

Gerrit-K commented Jan 4, 2024

git-forgit should be in your PATH, isn't that the case?

Apparently not. I never had and it was never causing issues, because I only use forgit's aliases, which are referencing the forgit:: functions from the shell plugin. But I apparently never used git-forgit or git forgit directly.

However, adding the bin folder to PATH (so that git-forgit is available) doesn't fix the issue with completions.

@sandr01d
Copy link
Collaborator

sandr01d commented Jan 5, 2024

Hi @Gerrit-K,

I don't know a lot about zinit or macOS, but I wrote the zsh completion functions for forgit so hopefully we can figure this out together 🙂

Additionally to git-forgit having to be in your PATH, the completion file (_git-forgit) needs to be in your $fpath is that the case? Do completions work when you use forgit as a git subcommand or not at all? E.g. git forgit <TAB> should print a list of all available commands.

I noticed there are no _git-* completion functions, but also no git-* commands on my system.

That's a bit odd and forgit needs the completion functions for the individual git commands for the completions to function properly. Could you please run the following in your zsh and let me know the results?

for line in $fpath; do grep _git-add "$line/"**/*(-.); done

Also can you post the content of the _git completion function on your system? The easiest way to obtain it is by running which _git.

Just to be sure could you let me know how you initialize completions in your .zshrc? For example, mine looks like this

autoload -Uz compinit
compinit

It would also be good to know which version of git you're using and where you installed it from.

@Gerrit-K
Copy link
Contributor Author

Gerrit-K commented Jan 5, 2024

Hey @sandr01d, first of all, thank you so much for the detailed answer and all the effort to help me ❤️ It might very well be just a niche edge case, but I really appreciate it!

To get back to your replies:

the completion file (_git-forgit) needs to be in your $fpath is that the case?

Yes ✔️

Do completions work when you use forgit as a git subcommand or not at all? E.g. git forgit <TAB> should print a list of all available commands.

Not at all, unfortunately. git forgit <TAB> just lists files from the current directory. git forgit works, though. When I hit enter, I get the forgit: missing command ... reply.

I noticed there are no _git-* completion functions, but also no git-* commands on my system.

That's a bit odd and forgit needs the completion functions for the individual git commands for the completions to function properly. Could you please run the following in your zsh and let me know the results?

for line in $fpath; do grep _git-add "$line/"**/*(-.); done

Sure, here's the (slighly anonymized 😉) result:

/Users/user/.zinit/completions/_git-forgit:                     add) _git-add ;;
zsh: no matches found: /usr/local/share/zsh/site-functions/**/*(-.)
/opt/homebrew/Cellar/zsh/5.9/share/zsh/functions/_git:(( $+functions[_git-add] )) ||
/opt/homebrew/Cellar/zsh/5.9/share/zsh/functions/_git:_git-add () {

Also can you post the content of the _git completion function on your system? The easiest way to obtain it is by running which _git.

_git function
❯  which _git
_git () {
        local _ret=1
        local cur cword prev
        cur=${words[CURRENT]}
        prev=${words[CURRENT-1]}
        let cword=CURRENT-1
        if (( $+functions[__${service}_zsh_main] ))
        then
                __${service}_zsh_main
        elif (( $+functions[__${service}_main] ))
        then
                emulate ksh -c __${service}_main
        elif (( $+functions[_${service}] ))
        then
                emulate ksh -c _${service}
        elif (( $+functions[_${service//-/_}] ))
        then
                emulate ksh -c _${service//-/_}
        fi
        let _ret && _default && _ret=0
        return _ret
}

Just to be sure could you let me know how you initialize completions in your .zshrc? For example, mine looks like this

autoload -Uz compinit
compinit

This is unfortunately a bit more convoluted in my setup, due to how zinit works. It's kind of similar to this config (which I've adapted, but diverged from, several years ago) with the matching call here. I can try to simplify my setup to see if it fixes the issue 👍

It would also be good to know which version of git you're using and where you installed it from.

Sure! It's 2.43.0 from Homebrew.

@sandr01d
Copy link
Collaborator

sandr01d commented Jan 8, 2024

/opt/homebrew/Cellar/zsh/5.9/share/zsh/functions/_git:(( $+functions[_git-add] )) ||
/opt/homebrew/Cellar/zsh/5.9/share/zsh/functions/_git:_git-add () {

_git-add appears to be present on your system and also in your $fpath. Not sure why it isn't being picked up by compinit though.

Do completions work when you use forgit as a git subcommand or not at all? E.g. git forgit should print a list of all available commands.

Not at all, unfortunately. git forgit just lists files from the current directory.

So what this essentially boils down to is _git-forgit is not properly picked up from compsys, the question is just why. Let's focus on this one first because, as far as forgit is involved, this does all the heavy lifting. git-forgit.zsh only makes sure the completions are also passed along to the functions and aliases. Given that _git-forgit appears to reside in a zinit specific directory (/Users/user/.zinit/completions/_git-forgit), which is not in the $fpath by default, could it be that zinit is adding this directory to the $fpath after compinit already ran? I've noticed you're using lucid, which is asynchronous. Maybe there is some sort of race condition (wild guess here)? Try placing _git-forgit inside one of the directories that are included in $fpath by default (/usr/local/share/zsh/site-functions is probably a good start) and check if the completions get picked up for forgit as a git subcommand. If it does, I think we'd need to take a closer look of your zinit/.zshrc setup, if it does not my guess would be something to how compinit is called.

@Gerrit-K
Copy link
Contributor Author

Hey, sorry for the delayed reply!

I think I've figured out what's happening. First of all, the reason why _git-add wasn't picked up, despite being in my $fpath was that .../zsh/functions/_git was shadowed by .../zsh/site-functions/_git. The former links to the completion installed by the zsh package whereas the latter links to a completion installed by git package. I found this out by luckily stumbling over this reddit post, where they suggest to simply remove the symlink from the git package. After that, the completions for git forgit <tab> worked correctly ✅

Next problem was to get the aliases working. When I source git-forgit.zsh from a fully loaded shell, everything seemed to be working. However, when I added that to my config, I got zsh: command not found: _git. Here, the issue was my zinit order. I roughly had this:

zi lucid for \
 completions \
 sbin'bin/*' \
 src'completions/git-forgit.zsh' \
    wfxr/forgit \
 atinit'zicompinit; zicdreplay' \
    zdharma-continuum/fast-syntax-highlighting

The idea (based on this example) was that:

  • all completion-providing plugins are loaded before fast-syntax-highlighting; zinit records, but not executes their compdef calls
  • at the initialization of fast-syntax-highlighting, compinit and zicdreplay are called; the latter basically re-runs all recorded compdef commands

However, git-forgit.zsh never actually got to the point of issuing compdef commands, because compinit was not yet called at this point, so _git was not available (triggering the cnf error from above).

I reordered the plugins so that forgit gets loaded immediately after syntax-highlighting, which fixed the cnf error, but the completions were still broken. This was due to zinit still suppressing and recording the compdef calls. So all that was missing was an additional zicdreplay command:

zi lucid for \
 atinit'zicompinit; zicdreplay' \
    zdharma-continuum/fast-syntax-highlighting
 completions \
 sbin'bin/*' \
 src'completions/git-forgit.zsh' \
 atload'zicdreplay' \
    wfxr/forgit \

With that, everything finally worked. It's not the most ideal solution and I'll probably continue working on it, but for now I'm happy that this case is solved.

I'm sorry to have bothered you with this, but I'm really grateful for your help, as I probably wouldn't have invested the time to fix this if you hadn't provided troubleshooting suggestions. Thank you!

@Gerrit-K
Copy link
Contributor Author

Fwiw, the changes from #340 fixed all issues described above and zinit is now handling the single completion file perfectly well 👏

@sandr01d
Copy link
Collaborator

Nice, thanks for the info! Also thanks for the write-up, what an interesting edge case.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants