[Bug]: `aspect completion zsh` does not contain flags from underlying Bazel
What happened?
- Load the aspect cli completions in your current shell:
source <(aspect completion zsh); compdef _aspect aspect - Now type
aspect<SPACE>and hit tab. The command names are completed properly - Now type
build<SPACE>and hit tab.
With the official Bazel command line completions, double-tab will provide a list of targets, or navigate through the directory hierarchy until targets are available, and typing - and hitting tab will provide autocompletion of Bazel's gajillion command line options. Neither of these work with Aspect's cli tool.
Version
Development (host) and target OS/architectures: macOS Ventura
Output of bazel --version: aspect 5.0.1
Version of the Aspect rules, or other relevant rules from your
WORKSPACE or MODULE.bazel file: Current HEAD of this repo
Language(s) and/or frameworks involved: Go
How to reproduce
See above
Any other information?
No response
Fund our work
- [ ] Sponsor our open source work by donating a bug bounty
Note, target completion is also missing, and that's not possible for cobra to generate so we'll have to study what bazel does.
Note, target completion is also missing, and that's not possible for cobra to generate so we'll have to study what bazel does.
I took a look through the bash & zsh auto-completion scripts that ships with Bazel. bash makes a best effort attempt to determine target names with sed on the BUILD file:
# Usage: _bazel__matching_targets <kind> <prefix>
#
# Prints target names of kind <kind> and starting with <prefix> in the BUILD
# file given as standard input. <kind> is a basic regex (BRE) used to match the
# bazel rule kind and <prefix> is the prefix of the target name.
_bazel__matching_targets() {
local kind_pattern="$1"
local target_prefix="$2"
# The following commands do respectively:
# Remove BUILD file comments
# Replace \n by spaces to have the BUILD file in a single line
# Extract all rule types and target names
# Grep the kind pattern and the target prefix
# Returns the target name
sed 's/#.*$//' \
| tr "\n" " " \
| sed 's/\([a-zA-Z0-9_]*\) *(\([^)]* \)\{0,1\}name *= *['\''"]\([a-zA-Z0-9_/.+=,@~-]*\)['\''"][^)]*)/\
type:\1 name:\3\
/g' \
| "grep" -E "^type:$kind_pattern name:$target_prefix" \
| cut -d ':' -f 3
}
the zsh completion script runs a bazel query for :all in the package:
_get_build_targets() {
local pkg=$1
local rule_re
typeset -a completions
case $target_type in
test)
rule_re=".*_test"
;;
build)
rule_re=".*"
;;
bin)
rule_re=".*_test|.*_binary"
;;
esac
completions=(${$(_bazel_b query "kind(\"${rule_re}\", ${pkg}:all)" 2>/dev/null)##*:})
if ( (( ${#completions} > 0 )) && [[ $target_type != bin ]] ); then
completions+=(all)
fi
echo ${completions[*]}
}
sed is too simplistic & running a query is too heavy and too slow IMO. @oncilla 's PR https://github.com/aspect-build/aspect-cli/pull/373 uses buildozer's print label which seems like the best approach:
func listBazelRules(ctx context.Context, bzlPackage string) ([]string, error) {
var stdout bytes.Buffer
var stderr strings.Builder
opts := &edit.Options{
OutWriter: &stdout,
ErrWriter: &stderr,
NumIO: 200,
}
if ret := edit.Buildozer(opts, []string{"print label", bzlPackage + ":all"}); ret != 0 {
return nil, fmt.Errorf("buildozer exit %d: %s", ret, stderr.String())
}