From a3b98a42233d266eefbb6c656d9a98315c7c6101 Mon Sep 17 00:00:00 2001 From: Farid NL <34426099+Farid-NL@users.noreply.github.com> Date: Fri, 3 May 2024 08:57:16 -0600 Subject: [PATCH] Use compsys completion system for zsh (#1569) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new `_rbenv` script will be autoloaded by zsh as long as it's found in $FPATH. It should be the package manager's responsibility to symlink or move this file into an appropriate location. Co-authored-by: Mislav Marohnić --- README.md | 20 +++++++++++++++++++- completions/_rbenv | 13 +++++++++++++ completions/rbenv.zsh | 20 -------------------- libexec/rbenv-help | 21 +++++++++++++++++++++ 4 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 completions/_rbenv delete mode 100644 completions/rbenv.zsh diff --git a/README.md b/README.md index dbf8d7f90..254be38d6 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,24 @@ This will get you going with the latest version of rbenv without needing a syste 3. Restart your shell so that these changes take effect. (Opening a new terminal tab will usually do it.) +#### Shell completions + +When _manually_ installing rbenv, it might be useful to note how completion scripts for various shells work. Completion scripts help with typing rbenv commands by expanding partially entered rbenv command names and option flags; typically this is invoked by pressing Tab key in an interactive shell. + +- The **bash** completion script for rbenv ships with the project and gets [loaded by the `rbenv init` mechanism](#how-rbenv-hooks-into-your-shell). + +- The **zsh** completion script ships with the project, but needs to be added to FPATH in zsh before it can be discovered by the shell. One way to do this would be to edit `~/.zshrc`: + + ```sh + # assuming that rbenv was installed to `~/.rbenv` + FPATH=~/.rbenv/completions:"$FPATH" + + autoload -U compinit + compinit + ``` + +- The **fish** completion script for rbenv ships with the fish shell itself and is not maintained by the rbenv project. + ### Installing Ruby versions The `rbenv install` command does not ship with rbenv out-of-the-box, but is provided by the [ruby-build][] plugin. @@ -286,7 +304,7 @@ name | default | description 1. Prepends `~/.rbenv/shims` directory to PATH. This is basically the only requirement for rbenv to function properly. -2. Installs shell completion for rbenv commands. +2. Installs bash shell completion for rbenv commands. 3. Regenerates rbenv shims. If this step slows down your shell startup, you can invoke `rbenv init -` with the `--no-rehash` flag. diff --git a/completions/_rbenv b/completions/_rbenv new file mode 100644 index 000000000..4e77c83d8 --- /dev/null +++ b/completions/_rbenv @@ -0,0 +1,13 @@ +#compdef rbenv + +_rbenv() { + local completions + + if [ "${#words}" -eq 2 ]; then + completions=(${(f)"$(rbenv help --complete-commands "${words[2]}")"}) + _describe 'rbenv commands' completions + else + completions="$(rbenv completions ${words[2,-2]})" + compadd - "${(ps:\n:)completions}" + fi +} diff --git a/completions/rbenv.zsh b/completions/rbenv.zsh deleted file mode 100644 index e6564cfd1..000000000 --- a/completions/rbenv.zsh +++ /dev/null @@ -1,20 +0,0 @@ -if [[ ! -o interactive ]]; then - return -fi - -compctl -K _rbenv rbenv - -_rbenv() { - local words completions - read -cA words - - emulate -L zsh - - if [ "${#words}" -eq 2 ]; then - completions="$(rbenv commands)" - else - completions="$(rbenv completions ${words[2,-2]})" - fi - - reply=("${(ps:\n:)completions}") -} diff --git a/libexec/rbenv-help b/libexec/rbenv-help index 8e5eaf055..55ded8291 100755 --- a/libexec/rbenv-help +++ b/libexec/rbenv-help @@ -151,6 +151,27 @@ print_usage() { fi } +if [ "$1" = "--complete-commands" ]; then + command_prefix="${2:-}" + seen=() + IFS=: read -d '' -r -a paths <<<"$PATH" || true + shopt -s nullglob + for path in "${paths[@]}"; do + for command in "${path}/rbenv-${command_prefix}"*; do + command_name="${command##*/}" + command_name="${command_name#rbenv-}" + command_name="${command_name#sh-}" + [[ " ${seen[*]} " != *" ${command_name} "* ]] || continue + seen+=("$command_name") + summary="" + eval "$(extract_initial_comment_block < "$command" | collect_documentation)" + [ -n "$summary" ] || continue + printf "%s:%s\n" "$command_name" "$summary" + done + done + exit 0 +fi + unset usage if [ "$1" = "--usage" ]; then usage="1"