Skip to content

Bash completion breaks on descriptions containing colons #2335

@TimSoethout

Description

@TimSoethout

My urfave/cli version is

v3 (main branch)

Checklist

  • Are you running the latest v3 release? The list of releases is here.
  • Did you check the manual for your release? The v3 manual is here
  • Did you perform a search about this problem? Here's the GitHub guide about searching.

Dependency Management

  • My project is using go modules.

Describe the bug

The generated bash completion script incorrectly parses token:description lines when the description itself contains colons.

The bash autocomplete template in autocomplete/bash_autocomplete has:

token="${line%%:*}"

Because the template is rendered via fmt.Sprintf, the %% is interpreted as an escape sequence that produces a single %. The rendered output becomes:

token="${line%:*}"

${line%:*} (single %) removes the shortest suffix from the last colon, which is incorrect. The correct bash parameter expansion is ${line%%:*} (double %%), which removes the longest suffix from the first colon.

This means a completion line like export:Export various configurations such as: compose-config, user-service gets its token parsed as the entire string minus the last : compose-config, user-service fragment, producing broken spurious completions via compgen -W.

To reproduce

  1. Define a command with a colon in its Usage string (e.g. Usage: "Export configs such as: compose-config")
  2. Source the generated bash completion script: source <(myapp completion bash)
  3. Press TAB to trigger completions
  4. Observe spurious completion entries split from the description text

Expected behavior

Only the command name (before the first colon) should appear as a completion candidate. Descriptions containing colons should not leak into the token list.

Additional context

The fix is to use %%%% in the template so that after fmt.Sprintf, the rendered script contains %% (greedy match from first colon):

token="${line%%%%:*}"  # template source
token="${line%%:*}"    # rendered output (correct)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions