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

Add zsh completion #9

Closed
lugoues opened this issue Mar 8, 2020 · 19 comments · Fixed by #309
Closed

Add zsh completion #9

lugoues opened this issue Mar 8, 2020 · 19 comments · Fixed by #309

Comments

@lugoues
Copy link

lugoues commented Mar 8, 2020

It would be awesome to tab complete the top rated entries.

Side note: All the tickets are because your tool is awesome :) 🥇

@Tchoupinax
Copy link

Could the tab autocomplete be compatible with bash ? Globally I think it should be handled by xoxide independently of the used shell.

Side note: I confirm, it is awesome 😍

@cole-h
Copy link
Contributor

cole-h commented Mar 12, 2020

Two things:

  1. I think completion for all supported shells should be created, eventually.
  2. I think that the tab completion should complete the closest match (e.g. what would display when you zoxide query the path) and cycle through all subsequent matches.

@ajeetdsouza
Copy link
Owner

I think this would be a great feature. I'm not too familiar with setting up shell completions, though, so it might take a while for this feature to land.

@fourjay
Copy link

fourjay commented Mar 16, 2020

FWIW, although my skills are limited, here is a bash completion I put together. It only completes with zq value (a list would be better) and the options.

_zoxide_completion() {
    local cur prev words cword
    _init_completion || return
    COMPREPLY=()
    case $prev in
    -takes_file)
        _filedir
        return
        ;;
    esac
    case ${cur} in
    -*)
        COMPREPLY=($(compgen -W '
        -V --version
        -h --help
        -i --interactive
        ' -- "${cur}"; ))
        [[ COMPREPLY == *= ]] || compopt +o nospace
        ;;
    *)
        # set -x
        # COMPREPLY=($(compgen -W "$( zq  "${cur}" | awk '{ print $NF}' )" -- "${cur}") )
        COMPREPLY=($(compgen -W "$( zq  "${cur}" | awk '{ print $NF}' )
        "  ) )
        ;;

    esac
} && complete -F _zoxide_completion -o nospace z

@xiaket
Copy link

xiaket commented Mar 21, 2020

I've used the solution provided by @fourjay and it is almost there, except maybe fuzzy path look up, which I think need to be supported within zoxide(because zoxide query does not provide a fuzzy search flag). I can see this is already raised in #34 .

@fourjay
Copy link

fourjay commented Jul 5, 2020

In the event folks are still looking at this, I've added support for the new query function to the completion
The sed parses out a subpath match. It's not perfect, but it's useful
The awk reformats to a nicer display for the competion popup
the mapfile is bash idiom to embed spaces in the COMPREPLY

The major change is in the catchall (the guts of the completion)

          mapfile -t _completions < <( zoxide query --list --score "${cur}" |
               sed 's|^[ ]*\([0-9]\+[ ]*\)\(.*/\(.*t.*\).*\)|\3 \2 \1|' |
               awk '{printf( "%-17.15s %35.35s %15s |\n", $1, $2, $3) }'
          )
          IFS=$'\n' COMPREPLY=(${_completions[@]})
          unset _completions

@NightMachinery
Copy link

@fourjay Perhaps send a PR?

@ajeetdsouza
Copy link
Owner

Related: marlonrichert/zsh-autocomplete has added support for zoxide.

@Lucretiel
Copy link

This should be relatively easy to implement via clap (via structopt), since clap has native support for generating completions for several popular shells: https://docs.rs/clap/2.33.3/clap/struct.App.html#method.gen_completions_to

@ajeetdsouza
Copy link
Owner

I tried playing around with z completions today on two different shells. Here's what I found:

  • On Elvish, if you type in z arg, Elvish expects completions to only start with arg. For this reason, Elvish cannot support z completions, since we will be supplying /absolute/paths/that/match/arg.
  • Fish allows arbitrary completions, but the experience is still unintuitive:
    • If you type z and hit TAB, all the results would start with / (since they're all absolute paths) - so Fish fills in that / for you. You have to manually delete the / before proceeding. The solution is to disable completions if the user hasn't typed anything.
    • If you type in z foo bar, Fish will only use the completions to replace bar. So you end up with something like z foo /home/bar which doesn't work. The solution here seems to be not providing completions if there's more than one argument.
    • z also acts as a regular cd command. Are the regular cd-able directories expected to show up on top of the list, above the directories retrieved from zoxide? That looks very odd / inconsistent.

So far, I'm still not convinced that this would be a useful feature to have.

@fourjay
Copy link

fourjay commented May 14, 2021

FWIW, I've not been using my attempt (much)
That said, I think the primary use case here is discovery.
Two sub points:

  1. completion is a standard discovery mechanism across a lot of shell commands.
    Yes, there are app specific ways to get similar results, but some (many) of us are reasonably conditioned to mash tab :-)
  2. It's still useful to see what other matches a given (fuzzy) string might have.
    Two subcases here:
    a) when there's a second match that on a new entry in the frecent Db.
    Completion gives easy view of the potential matches
    b) when not sure of what other entries are in the Db.

@fourjay
Copy link

fourjay commented May 19, 2021

Thinking about this a little more, fzf completion fills this role pretty well....
But from an overall consistency perspective, I'd prefer it could be triggered via tab
A little google, and I see that junegunn has already done some work along that line
https://github.com/junegunn/fzf#fuzzy-completion-for-bash-and-zsh

@mlncn
Copy link

mlncn commented Jun 3, 2021

If i haven't typed anything, z should work like cd (as it does now)

If i've typed something, it should absolutely cycle through top suggestions, pretty please! Guessing what the top suggestion is, and what additional letters to type to get the right one, is no fun.

EDIT: Actually listing and not cycling would give me everything i want. Same way cd lists all potential completions. z can do the same, and as long as the top match, the one that will be selected if i press enter, is first, that's all the information i'm looking for.

I type: z ex and press tab.

I see:

~/Documents/example
~/Pictures/exes
/media/files/example

If i'm looking for /media/files/example i know to press space and fi to jump to the right place. If i'm looking for ~/Pictures/exes i know to type an e. If i'm looking for ~/Documents/example i know i can just press enter already. Without this essential feedback, i'm jumping blindly to what i hope is the folder i intend.

@timqi
Copy link

timqi commented Jul 10, 2021

paste code below in your .zshrc can support z completions
@ajeetdsouza

_zoxide_zsh_tab_completion() {
    (( $+compstate )) && compstate[insert]=menu
    local keyword="${words:2}"
    local completions=(${(@f)"$(zoxide query -l "$keyword")"})


    if [[ ${#completions[@]} == 0 ]]; then
        _files -/
    else
        compadd -U -V z "${(@)completions}"
    fi
}

if [ "${+functions[compdef]}" -ne 0 ]; then
    compdef _zoxide_zsh_tab_completion z 2> /dev/null
fi

@ajeetdsouza
Copy link
Owner

ajeetdsouza commented Jul 29, 2021

@fourjay as you suggested, I had a look at how fzf is doing completions, and I think it works quite well for zoxide:

  • By default, z completions are the same as cd. It only completes actual directory names.
  • If the query ends in ** (customizable), we can switch to an fzf completer, similar to the zi command. We can come up with better defaults for zi to not let it occupy the whole screen.
  • If the query has more than one word, it cannot be completed correctly, so there would be no completions.

Since fzf already has completions that work like this on a variety of common UNIX commands (vim, kill, etc.) which are quite popular, I think it's a reasonably good default for a project like zoxide. @kidonng, I'd love your thoughts on this too.

So, for example, if you were in /home/foo:

  • z Do<TAB> will open the standard autocompleter and give you results like Documents/ and Downloads/, similar to cd.
  • z Do**<TAB> will open up fzf and give you results like /home/foo/git/Dotfiles in an interactive menu.

I think this approach would be the most consistent, since it segregates the completions for "z as a cd command" from the "z as an autojumper". The only downside is that the * character is difficult to type, but I'm willing to live with that since it would be customizable by the user.


@mlncn I've thought about what you described, but I don't think it would work for everyone since I myself often use z ex<TAB> to see what's inside the current folder, and it would be quite messy and confusing if zoxide results got added there. I suspect you might like zsh-autocomplete, though.

@ajeetdsouza
Copy link
Owner

ajeetdsouza commented Sep 3, 2021

For anyone interested, take a look at #257. I've only implemented Bash completions at the moment, but I'd love to know what you think:

  • Completions only work when there is one word (therefore completions are always valid).
  • By default, it uses the same completions as cd.
  • If the query ends with **, it opens up fzf and does an interactive search (similar to fzf's builtin completions).

If it works well, we can hopefully write completions for other shells in line with this. For now, you can test it out like so:

cargo install --git https://github.com/ajeetdsouza/zoxide --branch bashcomp

Update: Fish completions are done too.

@xenoterracide
Copy link

xenoterracide commented Oct 21, 2021

hmm... completions don't seem to be doing anything other than the default for me on zsh. 0.7.5

zinit wait has"zoxide" atinit'eval "$(zoxide init zsh --hook pwd --cmd cd)"' for zdharma/null

@ajeetdsouza
Copy link
Owner

I've just merged support for zsh completions, it will be released in the next version of zoxide. Sorry this took so long, but this is finally an implementation that I'm happy with!

# press <space><tab> to start interactive completions.

z foo<tab> # shows the same completions as cd
z foo<space><tab> # shows interactive completions via zoxide

@OrbitalHustler
Copy link

OrbitalHustler commented Mar 20, 2023

This doesn't properly work for me like it works for cd. I'm using the following zsh completion:
zstyle ':completion:*' completer _expand _expand_alias _complete _correct _ignored _approximate

Which allows me to complete the hello_world directory by doing cd hwo<TAB>, however z hwo<TAB> doesn't work. How can I obtain that result?

Edit: may be the issue described in #513

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.