zsh autocompletion for a shell function

I have this shell function


function cdd() {
  DEST=$1
  cd "${DEV}/${DEST}/"
}

I'd like to type cdd <tab> and autocomplete directory names from inside ${DEV}/${DEST}

Having ChatGPT Solve My Difficulty Reading Docs

I started by reading a zsh completion guide blog post I got from a web search. I see a lot about using zstyle to configure the defaults, not much to address my ask.

I continued by looking at the Zsh Completion System docs, which are famously dense.

I lost patience after ten minutes. This autocomplete stuff is an incidental problem to other goals, not my main goal, so reading these docs for hours sucks.

I asked ChatGPT. She seemed so confident, so all-knowing

Now, you need to create a custom completion function that provides the directory suggestions based on the $DEV path:

# Custom completion function for cdd
_cdd_complete() {
  local cur=${words[2]}
  # Complete directories in the $DEV path
  compadd -o nospace -o filenames -- $(compgen -d "${DEV}/${cur}")
}

# Register the custom completion function for cdd
compdef _cdd_complete cdd

Assuming she's right, what have I learned? Have I learned less than if I'd stumbled on a random blog post with this answer? I copy/pasted into .zshrc


; cdd _cdd_complete:3: command not found: compgen
                                    cdd
--         -o         filenames  nospace

There's always a detail to get right. She tells me

The error you're encountering is due to the fact that compgen, which is commonly used in Bash for generating completion lists, isn't available in Zsh.

Thus I learned that chatGPT doesn't really know her own context, a lesson I've learned again and again and again.

Her second attempt:


# Custom completion function for cdd
_cdd_complete() {
  # Use _files to generate a list of directories in $DEV
  _files -W "${DEV}" -/
}

# Register the custom completion function for cdd
compdef _cdd_complete cdd

It worked immediately. What have I learned?

Learnings

  1. You use compdef to bind an underscore function to another function. Now This github doc on zsh completions makes sense.
  2. The Zsh completion system docs are approachable once you know what you're looking for. They're like man bash that way. In the link above, it clearly says "[functions] beginning ‘_’ are called by the completion code. The shell functions of this set, which implement completion behaviour and may be bound to keystrokes, are referred to as ‘widgets’. These proliferate as new completions are required."
  3. _files is a built in Utility Function. It's a wrapper around another function. They're both useful sounding; probably reading all of the Utility Functions should be on my ToDo list
  4. I also learned I'm grateful that chatGPT exists and helps me move quicker, even as I'm sad that I wasn't forced to wade through this problem for days. I miss the revelation after suffering.