aspect-cli icon indicating copy to clipboard operation
aspect-cli copied to clipboard

[Bug]: `aspect completion zsh` does not contain flags from underlying Bazel

Open shs96c opened this issue 3 years ago • 2 comments

What happened?

  1. Load the aspect cli completions in your current shell: source <(aspect completion zsh); compdef _aspect aspect
  2. Now type aspect<SPACE> and hit tab. The command names are completed properly
  3. 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

shs96c avatar Nov 23 '22 10:11 shs96c

Note, target completion is also missing, and that's not possible for cobra to generate so we'll have to study what bazel does.

alexeagle avatar Nov 30 '22 15:11 alexeagle

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())
	}

gregmagolan avatar Jan 24 '23 00:01 gregmagolan