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

Generate zsh autoload completion function file #2402

Open
Nevon opened this issue Apr 26, 2024 · 0 comments
Open

Generate zsh autoload completion function file #2402

Nevon opened this issue Apr 26, 2024 · 0 comments

Comments

@Nevon
Copy link
Contributor

Nevon commented Apr 26, 2024

I'll preface this by saying that the completion system is quite the arcane mystery to me, so please forgive my ignorance here.

We can generate completions for bash and zsh from yargs. This simply prints a piece of bash or zsh code that the user can put into their .zprofile or equivalent. The output for this is defined here. A zsh example looks like this:

###-begin-my-command-completions-###
#
# yargs command completion script
#
# Installation: /Users/nevon/.volta/tools/image/packages/my-package/bin/my-command completion >> ~/.zshrc
#    or /Users/nevon/.volta/tools/image/packages/my-package/bin/my-command completion >> ~/.zsh_profile on OSX.
#
_my_command_yargs_completions()
{
  local reply
  local si=$IFS
  IFS=$'
' reply=($(COMP_CWORD="$((CURRENT-1))" COMP_LINE="$BUFFER" COMP_POINT="$CURSOR" /Users/nevon/.volta/tools/image/packages/my-package/bin/my-command --get-yargs-completions "${words[@]}"))
  IFS=$si
  _describe 'values' reply
}
compdef _my_command_yargs_completions my-command
###-end-my-command-completions-###

This is all well and good if the user invokes the completion command and copies the output into some file that gets sourced. However, when this command is packaged up for distribution, such as in homebrew, the package manager would like to manage the completions in files that it can add or remove from the shell path when the package is installed or uninstalled.

Zsh has this functionality baked in, in the form of autoloaded files. The gist is that you put a file named _[command] (for example _git) into a directory that's in the fpath, with the first line of the file being #compdef command (for example #compdef git). Whenever the shell needs completions for the command, it executes that file. The equivalent of the completion script above would be:

#compdef my-command

_my_command_yargs_completions()
{
  local reply
  local si=$IFS
  IFS=$'
' reply=($(COMP_CWORD="$((CURRENT-1))" COMP_LINE="$BUFFER" COMP_POINT="$CURSOR" /Users/nevon/.volta/tools/image/packages/my-package/bin/my-command --get-yargs-completions "${words[@]}"))
  IFS=$si
  _describe 'values' reply
}
_my_command_yargs_completions "$@"

Today I'm having to work around this by having the installer execute my-command completion > _my-command and then doing some dirty sed tricks to get it into the autoload format, which will definitely break at some point when the completion template gets updated.

I'm not sure what a good solution for this would be. Adding a --format=autoload flag or something to the completion command to return the completion file in a format that can be autoloaded?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants