ajeetdsouza / zoxide

A smarter cd command. Supports all major shells.
MIT License
22.11k stars 537 forks source link

Can't setup completions on ZSH #471

Open delucca opened 1 year ago

delucca commented 1 year ago

Hey everyone

I'm trying to setup completions on ZSH but not being able to do so. My cdi command works properly (if I type cdi and then Enter if opens a FZF selector as expected), but for some reason the completions are not working.

Here is my ~/.zshrc file: https://pastebin.com/4GM136Tf

Here is what I've already discovered:

What should I do?

raine commented 1 year ago

Zsh completion is not working for me either.

I assume z foo<tab> should show results that match foo. For me it autocompletes files and directories in the current directory.

timhansinger commented 1 year ago

Zsh completion is not working for me either.

I assume z foo<tab> should show results that match foo. For me it autocompletes files and directories in the current directory.

Hello raine,

if you check the documentation you need to use:

z foo<space><tab>

Best Tim

ngocphamm commented 1 year ago

I think I am seeing the same issue, and maybe zinit is the common point I have with @delucca here.

zz <TAB> works and show FZF interactive window

z te <TAB> just list all the directories within the current directory, while z te<ENTER> does take me to the correct .../test folder.

This is the end part of my .zshrc file, but basically I'm loading zoxide after compinit (which is being called with zicompinit there)

zinit wait"0c" lucid light-mode for \
  atinit"ZINIT[COMPINIT_OPTS]=-C; zicompinit; zicdreplay" zdharma-continuum/fast-syntax-highlighting \
  atload"!_zsh_autosuggest_start" zsh-users/zsh-autosuggestions \
  blockf zsh-users/zsh-completions

# Zoxide - very much like (better) fasd
zinit ice wait"1" lucid from"gh-r" as"null" sbin \
  atclone"./zoxide init --no-cmd zsh > init.zsh" \
  atpull"%atclone" \
  src"init.zsh" \
  nocompile"!"
zinit light ajeetdsouza/zoxide
fredcallaway commented 1 year ago

EDIT: probably don't follow this advice. See updated solution below.

Also using zinit and ran into this issue. It seems that the critical think is to load compinit before running zoxide init.

zinit ice wait"2" as"command" from"gh-r" lucid \
  mv"zoxide*/zoxide -> zoxide" \
  atclone"./zoxide init zsh > init.zsh" \
  atpull"%atclone" src"init.zsh" nocompile'!'
zinit light ajeetdsouza/zoxide

autoload -U compinit && compinit -u  # BEFORE zoxide init
eval "$(~/.local/share/zinit/plugins/ajeetdsouza---zoxide/zoxide init zsh)"

Note that just zoxide init didn't work because of how zinit makes commands available without modifying PATH.

ngocphamm commented 1 year ago

@fredcallaway With the way we are calling zoxide with zinit there, I think we already did the eval "$(zoxide init zsh)", and according to zinit's wait, it should be after compinit. Of course there might be so many things going on here due to zinit (that I don't entirely understand yet), but it should have worked that way.

Not sure if there's some sort of debugging messaging we can add temporarily to the files to see the order of execution and make sure we are doing it correctly according to both zinit, and zoxide documentation.

fredcallaway commented 1 year ago

Thanks for pointing this out @ngocphamm. I hadn't bothered to try to understand the zinit incantation. I should also report that the "solution" above doesn't actually work reliably. (Not sure how it ever worked at all TBH). But what does seem to do the trick is just manually adding compdef __zoxide_z_complete j after autoload -U compinit. I have no idea why the compdef line in zoxide init output doesn't accomplish this, but hey, if it works it works.

ngocphamm commented 1 year ago

@fredcallaway I think I just figured out the issue I have with this. In my particular case, because I do not want the zi alias (as it's for zinit), I used the atclone"./zoxide init zsh --no-cmd > init.zsh" configuration. That --no-cmd would not generate the __zoxide_z_complete function for me at all.

Once I get that function back in the init.zsh, I can put zoxide anywhere in the zinit plugin list, just before zicompinit; zicdreplay and that works.

For your case, I figured because zoxide does require the eval "$(zoxide init zsh)" to go after autoload -U compinit, and maybe for you, zinit already loads the init.zsh for the zoxide plugin, before autoload -U compinit, so even when you do eval "$(~/.local/share/zinit/plugins/ajeetdsouza---zoxide/zoxide init zsh)" afterwards, it doesn't work reliably?

Related to this discussion https://github.com/ajeetdsouza/zoxide/discussions/446#discussioncomment-4622771

rrpolanco commented 1 year ago

I'm having issues with interactive fzf completion when typing: zSpacestartTab Nothing happens. I was expecting the fzf window to appear with matching entries for "start".

I have installed fzf and zoxide via zinit:

zinit wait lucid light-mode \
    from'gh-r' \
    id-as'auto' \
    nocompile \
    dl'https://raw.githubusercontent.com/junegunn/fzf/master/bin/fzf-tmux' \
    dl'https://raw.githubusercontent.com/junegunn/fzf/master/shell/completion.zsh -> completion.zsh' \
    dl'https://raw.githubusercontent.com/junegunn/fzf/master/shell/key-bindings.zsh -> key-bindings.zsh' \
    dl'https://raw.githubusercontent.com/junegunn/fzf/master/man/man1/fzf-tmux.1 -> $ZPFX/man/man1/fzf-tmux.1' \
    dl'https://raw.githubusercontent.com/junegunn/fzf/master/man/man1/fzf-tmux.1 -> man/fzf-tmux.1' \
    dl'https://raw.githubusercontent.com/junegunn/fzf/master/man/man1/fzf.1 -> man/fzf.1' \
    atclone'mkdir -p $ZPFX/{bin,man/man1}' \
    atclone'ln -nsvf "$PWD/man/"*.1 "${ZINIT[MAN_DIR]}/man1"' \
    atpull'%atclone' \
    pick'/dev/null' \
    sbin'fzf' \
    sbin'fzf-tmux' \
    multisrc'key-bindings.zsh' \
    multisrc'completion.zsh' \
  for @junegunn/fzf

# https://github.com/ajeetdsouza/zoxide
zinit wait lucid light-mode for \
  from'gh-r' \
  id-as'auto' \
  as'command' \
  atinit'export _ZO_DATA_DIR=$HOME/.zoxide' \
  atload'
    eval "$(zoxide init --no-aliases zsh)"
    alias z="__zoxide_z"
  ' pick'zoxide/zoxide' \
  @ajeetdsouza/zoxide

Any tips on how I can troubleshoot this?

fredcallaway commented 1 year ago

zinit is a complete black box for me, but this works for me.

zinit wait lucid from"gh-r" as"null" for \
    sbin"fzf" @junegunn/fzf \
    ... # other plugins

... # stuff

zinit ice as"command" from"gh-r" lucid \
  mv"zoxide*/zoxide -> zoxide" \
  atclone"./zoxide init --cmd j zsh > init.zsh" \
  atpull"%atclone" src"init.zsh" nocompile'!'
zinit light ajeetdsouza/zoxide

... # more stuff

autoload -U compinit && compinit -u
compdef __zoxide_z_complete j  # I use j as my zoxide key
ngocphamm commented 1 year ago

@rrpolanco I think it's supposed to be z phrase<space><Tab>

https://github.com/ajeetdsouza/zoxide#getting-started

raine commented 1 year ago

Why does there have to be a space? It's quite nonidiomatic for zsh.

rrpolanco commented 1 year ago

@fredcallaway Your zinit plugin installation of zoxide doesn't work. The error was related with the mv"zoxide*/zoxide -> zoxide" ice not finding the binary. I was able to fix it and move on but j tab completions still did not work for me.

@ngocphamm When I do z phrase<space><Tab> I don't get an interactive list. This is what I get: zoxide_issue_471

fredcallaway commented 1 year ago

Sorry for giving you a broken example. For the example you showed, it looks like the zsh-autosuggestions plugin (or whatever is giving you the fish-style completions) might be causing the issue. The funny 'z#...' string is what you get from the correct zoxide interactive tab completion.

Ah this gives me an idea. Does __zoxide_zi work? It should give you an interactive fzf list of recent directories. I think that would tell you if the interactive mode is itself broken or if it is just getting superseded by something else.

ngocphamm commented 1 year ago

@rrpolanco This is what I have.

zinit as"null" wait"0a" lucid light-mode from"gh-r" lbin"!" lman completions for \
  bpick"*darwin_arm64*" lbin"!fzf*" \
    dl'https://raw.githubusercontent.com/junegunn/fzf/master/bin/fzf-tmux;
       https://raw.githubusercontent.com/junegunn/fzf/master/shell/completion.zsh;
       https://raw.githubusercontent.com/junegunn/fzf/master/shell/key-bindings.zsh;
       https://raw.githubusercontent.com/junegunn/fzf/master/man/man1/fzf-tmux.1;
       https://raw.githubusercontent.com/junegunn/fzf/master/man/man1/fzf.1' \
    multisrc"{key-bindings,completion}.zsh" \
    junegunn/fzf \
  nocompile"!" \
    atclone"./zoxide init zsh --no-cmd > init.zsh" \
    atpull"%atclone" \
    src"init.zsh" \
    ajeetdsouza/zoxide 

And those are before the load of those completion, highlighting, and autosuggestions that I also use

zinit wait"0c" lucid light-mode for \
  atinit"ZINIT[COMPINIT_OPTS]=-C; zicompinit; zicdreplay" zdharma-continuum/fast-syntax-highlighting \
  atload"!_zsh_autosuggest_start" zsh-users/zsh-autosuggestions \
  blockf zsh-users/zsh-completions

The dl, lbin and lman ice are provided by those

zinit light-mode for \
  zdharma-continuum/zinit-annex-binary-symlink \
  zdharma-continuum/zinit-annex-linkman \
  zdharma-continuum/zinit-annex-patch-dl \

I think zoxide no longer uses --no-aliases and is using --no-cmd.

I use that because by default the aliases are z and zi, and zi also zinit, which I like to keep that way. so I later have

alias z=__zoxide_z
alias zz=__zoxide_zi
theeternalsw0rd commented 2 months ago

This is what I used to get tab completion working, at least the basic kind that cd normally has that tab completes within the current working directory. I'm a new user, so am unaware of what additional tab completion functionality may be available when working normally. I will say that tab completion on __zoxide_z does not work at all.

if [ `command -v zoxide` ]; then
  eval "$(zoxide init --no-cmd zsh)"
  function cd() {
    __zoxide_z $@
  }
fi
ajeetdsouza commented 3 weeks ago

To those facing issues with completions - have you initialized zoxide at the end of your .zshrc as mentioned in the README? Among other things, one of the reasons this is necessary is so that zoxide gets called after compinit is initialized.

Secondly, is compinit being initialized in your .zshrc? Most plugin managers take care of this, but if it isn't getting initialized, zoxide will not be able to run completions.

Thirdly, are you initializing zoxide using the recommended way - eval "$(zoxide init zsh)"? I'm not sure how zinit works, so I can't say for sure, but I have seen a couple of threads where zinit has broken completions for users before.