Skip to content

fix tab completion of namespaced targets in zsh and bash - #559

Open
ybai08 wants to merge 1 commit into
magefile:masterfrom
ybai08:fix-558-namespace-completion
Open

ybai08 wants to merge 1 commit into
magefile:masterfrom
ybai08:fix-558-namespace-completion

Conversation

@ybai08

@ybai08 ybai08 commented Oct 18, 2026

Copy link
Copy Markdown

Fixes #558

With a namespace such as type Migration mg.Namespace, mage -autocomplete prints migration:create, migration:down, ... but neither the zsh nor the bash script completes them.

zsh: _describe reads each entry as name:description, so migration:create was offered as migration with the description create, and the other targets in the namespace were dropped. The script now escapes the colons (${(@)targets//:/\\:}) before calling _describe.

bash: : is in COMP_WORDBREAKS by default, so the colon splits the word. On bash 3.2 (macOS), mage migration:<TAB> turned into mage migration:migration:. On bash 4+, COMP_WORDS[COMP_CWORD] is just the text after the colon, so nothing matched. The script now takes the current word from COMP_LINE up to COMP_POINT. When : is a word break, it also removes the part up to the last : from each match, because bash only replaces the text after that point. This is the same approach bash-completion's __ltrim_colon_completions uses, without depending on bash-completion. fish and PowerShell are not affected and are unchanged.

Tests: TestBashCompletionNamespacedTargets sources the generated bash script with a stand-in mage that prints namespaced targets, sets COMP_LINE/COMP_POINT/COMP_WORDS the way bash does, and checks COMPREPLY. TestZshCompletionNamespacedTargets stubs _describe and checks that the target names reach it with their colons escaped. Both skip when the shell isn't installed, and both skip on Windows. Before the fix, 3 of the 6 bash cases and the zsh test fail.

What was run (macOS arm64, Go 1.27.1, zsh 5.9, /bin/bash 3.2.57):

  • go test -v -vet=all -tags CI -race ./...: everything passes except TestBootstrap. That test fails the same way on master here, because GOPATH isn't set in the environment (stat bin/mage).
  • go vet -tags CI ./... and gofmt -l .: clean.
  • golangci-lint run ./...: no findings in the changed files. CI pins v2.11.2, but that version can't load Go 1.27 export data, so v2.15.0 was used. Its only findings are 156 exhaustruct_v5 hits that are identical on master; that linter is newer than the repo's config.
  • Real interactive shells, driven through a pty with a magefile containing a namespace: zsh (via zpty) now offers migration:create migration:down migration:up for mage <TAB> and mage migration:<TAB>, and migration:down for mage migration:d<TAB>. bash 3.2 completes mage migration:d<TAB> to mage migration:down and mage fmt migration:u<TAB> to mage fmt migration:up.

Not run: bash 4/5 interactively (the unit test simulates its word splitting), Windows, Linux.

zsh's _describe treats the first unescaped ':' in each entry as the
name/description separator, so 'migration:create' was offered as
'migration' with the description 'create', and the remaining targets of
the namespace were dropped. Escape the colons before handing the list
to _describe.

bash splits words at ':' (it is in COMP_WORDBREAKS by default), so
'mage migration:d<TAB>' completed against 'd' and found nothing. Take
the current word from COMP_LINE instead and strip the part up to the
last ':' from each match, since bash only replaces the text after it.

Fixes magefile#558
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: mage tab completion breaks for namespaced targets (zsh)

1 participant