Bash & Zsh Tab Completion: A Mill Build Tool Guide

## Enhancing Command-Line Completion with Descriptions

Command-line interfaces (CLIs) are powerful tools, but remembering every flag‌ and ​option can​ be challenging. Effective tab completion significantly improves usability, and a refined approach can make it even better⁤ by displaying helpful descriptions‍ alongside your⁣ completions. This article explores how to achieve this,‌ ensuring you ⁣get the details you need right at your fingertips.

### The⁢ Problem‍ with Ambiguous‌ Completions

Traditionally,tab completion⁤ aims to provide a concise list of possible commands or options. Though, ​sometimes you want more context – ⁤a fast reminder ⁢of what a particular option *does*. Simply hitting `` ​should reveal this information without disrupting your workflow. The challenge lies in triggering the ‌display of descriptions without introducing unwanted text⁢ into your command.

Standard completion systems frequently enough struggle with this. When a completion is ambiguous – meaning multiple possibilities exist – Bash and Zsh typically show both the completion *and* its associated description. But⁢ what if you want‍ this behavior even when there’s only one possible completion?

### A Solution:​ Intentional‌ Ambiguity

The key ⁣is to intentionally create ambiguity. ​By adding a secondary, trimmed completion alongside ​the⁣ primary one, you ⁣force the shell‌ to display‌ the⁢ description. This approach works reliably across both Bash and Zsh, providing a ⁢consistent experience.

Here’s how you can implement this strategy:

#### Bash Implementation

Utilize‍ the​ `_complete_foo_bash` function to ⁣achieve this.

1. First, ⁢define the `IFS` (Internal Field Separator) ​to handle whitespace correctly.
2. Than,⁣ generate your completions using a helper function, `_generate_foo_completions`, passing the current word index (`$COMP_CWORD`)‍ and the words entered so far (`${COMP_WORDS[@]}`).
3. Store the raw completions in an array called ⁤`raw`.
4. ⁢ Create a new array, `trimmed`, and populate it with the ‍raw completions.
5. If the `raw` array contains only one element, append a trimmed version of that element​ to the `trimmed` array. This‍ trimmed version removes the descriptive text,creating the intentional ambiguity.
6.assign the `trimmed` array ⁢to `COMPREPLY`, which Bash uses to display ⁤the completions.

here’s the code:

“`bash
_complete_foo_bash() {
​ local IFS=$’n’
local raw=($(_generate_foo_completions “$COMP_CWORD” “${COMP_WORDS[@]}”))
local trimmed=()
trimmed+=( “${raw[@]}” )

⁢if (( ${#raw[@]} == 1 )); then
‍ trimmed+=(‍ “${raw[0]%%:*}” )
fi

COMPREPLY=( “${trimmed[@]}” )
}
“`

This ensures ‌that even ⁢a single completion will trigger the⁣ display of its description, while the ‌trimmed ⁣version prevents the‌ description from being inserted into your command.

#### ​Zsh Implementation

The process​ is similar in Zsh, using ⁤the `_complete_foo_zsh` function.

1. ​ Declare local arrays `raw` and `trimmed`.
2. ⁤ Set the⁣ `IFS` to handle whitespace.
3. ⁢Generate completions using `_generate_foo_completions`, passing the current word (`$CURRENT`) and the words entered (`${words[@]}`).
4. Iterate through the ⁣`raw` ‌completions, adding the trimmed versions‍ (without ⁢the description) to the `trimmed` array.
5.If there’s only one completion, append both the ⁢trimmed version and the original to ⁢both `trimmed` and ‍`raw` arrays.⁤ This is crucial as Zsh’s `compadd` function expects parallel arrays of descriptions and tokens.
6. Use `compadd -d raw — $trimmed` to add the completions to the completion‍ list. The ​`-d` flag specifies the descriptions, and the `–` separates ⁢the descriptions from the tokens.

Here’s the Zsh code:

“`bash
_complete_foo_zsh() {
local -a raw trimmed

Leave a Comment