nix

configuration files that power my machines
Log | Files | Refs | README | LICENSE

_bazel (10238B)


      1 #compdef bazel
      2 
      3 # Copyright 2015 The Bazel Authors. All rights reserved.
      4 #
      5 # Licensed under the Apache License, Version 2.0 (the "License");
      6 # you may not use this file except in compliance with the License.
      7 # You may obtain a copy of the License at
      8 #
      9 #    http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 # Unless required by applicable law or agreed to in writing, software
     12 # distributed under the License is distributed on an "AS IS" BASIS,
     13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 # See the License for the specific language governing permissions and
     15 # limitations under the License.
     16 
     17 # Installation
     18 # ------------
     19 #
     20 # 1. Add this script to a directory on your $fpath:
     21 #     fpath[1,0]=~/.zsh/completion/
     22 #     mkdir -p ~/.zsh/completion/
     23 #     cp scripts/zsh_completion/_bazel ~/.zsh/completion
     24 #
     25 # 2. Optionally, add the following to your .zshrc.
     26 #     zstyle ':completion:*' use-cache on
     27 #     zstyle ':completion:*' cache-path ~/.zsh/cache
     28 #
     29 #   This way, the completion script does not have to parse Bazel's options
     30 #   repeatedly.  The directory in cache-path must be created manually.
     31 #
     32 # 3. Restart the shell
     33 #
     34 # Options
     35 # -------
     36 #  completion:init:bazel:* cache-lifetime
     37 #    Lifetime for the completion cache (if turned on, default: 1 week)
     38 
     39 local curcontext="$curcontext" state line
     40 
     41 : ${BAZEL_COMPLETION_PACKAGE_PATH:=%workspace%}
     42 : ${BAZEL:=bazel}
     43 _bazel_b() { ${BAZEL} --noblock_for_lock "$@" 2>/dev/null; }
     44 
     45 # Default cache lifetime is 1 week
     46 zstyle -s ":completion:${curcontext}:" cache-lifetime lifetime
     47 if [[ -z "${lifetime}" ]]; then
     48   lifetime=$((60*60*24*7))
     49 fi
     50 
     51 _bazel_cache_policy() {
     52   local -a oldp
     53   oldp=( "$1"(Nms+${lifetime}) )
     54   (( $#oldp ))
     55 }
     56 
     57 _set_cache_policy() {
     58   zstyle -s ":completion:*:$curcontext*" cache-policy update_policy
     59 
     60   if [[ -z "$update_policy" ]]; then
     61     zstyle ":completion:$curcontext*" cache-policy _bazel_cache_policy
     62   fi
     63 }
     64 
     65 # Skips over all global arguments.  After invocation, OFFSET contains the
     66 # position of the bazel command in $words.
     67 _adapt_subcommand_offset() {
     68   OFFSET=2
     69   for w in ${words[2,-1]}; do
     70     if [[ $w == (#b)-* ]]; then
     71       (( OFFSET++ ))
     72     else
     73       return
     74     fi
     75   done
     76 }
     77 
     78 # Retrieve the cache but also check that the value is not empty.
     79 _bazel_safe_retrieve_cache() {
     80   _retrieve_cache $1 && [[ ${(P)#2} -gt 0 ]]
     81 }
     82 
     83 # Puts the name of the variable that contains the options for the bazel
     84 # subcommand handed in as the first argument into the global variable
     85 # _bazel_cmd_options.
     86 _bazel_get_options() {
     87   local lcmd=$1
     88   _bazel_cmd_options=_bazel_${lcmd}_options
     89   _bazel_cmd_args=_bazel_${lcmd}_args
     90   if [[ ${(P)#_bazel_cmd_options} != 0 ]]; then
     91     return
     92   fi
     93   if _cache_invalid BAZEL_${lcmd}_options || _cache_invalid BAZEL_${lcmd}_args \
     94     || ! _bazel_safe_retrieve_cache BAZEL_${lcmd}_options ${_bazel_cmd_options} \
     95     || ! _retrieve_cache BAZEL_${lcmd}_args ${_bazel_cmd_args}; then
     96     if ! eval "$(_bazel_b help completion)"; then
     97       return
     98     fi
     99     local opts_var
    100     if [[ $lcmd == "startup_options" ]]; then
    101       opts_var="BAZEL_STARTUP_OPTIONS"
    102     else
    103       opts_var="BAZEL_COMMAND_${lcmd:u}_FLAGS"
    104     fi
    105     local -a raw_options
    106     if ! eval "raw_options=(\${(@f)$opts_var})"; then
    107       return
    108     fi
    109 
    110     local -a option_list
    111     for opt in $raw_options; do
    112       case $opt in
    113         --*"={"*)
    114           local lst="${${opt##*"={"}%"}"}"
    115           local opt="${opt%%=*}="
    116           option_list+=("${opt}:string:_values '' ${lst//,/ }") ;;
    117         --*=path)
    118           option_list+=("${opt%path}:path:_files") ;;
    119         --*=label)
    120           option_list+=("${opt%label}:target:_bazel_complete_target") ;;
    121         --*=*)
    122           option_list+=("${opt}:string:") ;;
    123         *)
    124           option_list+=("$opt") ;;
    125       esac
    126     done
    127 
    128     local -a cmd_args
    129     local cmd_type
    130     if eval "cmd_type=\${BAZEL_COMMAND_${lcmd:u}_ARGUMENT}" && [[ -n $cmd_type ]]; then
    131       case $cmd_type in
    132         label|label-*)
    133           cmd_args+=("*::${cmd_type}:_bazel_complete_target_${cmd_type//-/_}") ;;
    134         info-key)
    135           cmd_args+=('1::key:_bazel_info_key') ;;
    136         path)
    137           cmd_args+=('1::profile:_path_files') ;;
    138         "command|{"*"}")
    139           local lst=${${cmd_type#"command|{"}%"}"}
    140           cmd_args+=("1::topic:_bazel_help_topic -- ${lst//,/ }") ;;
    141       esac
    142     fi
    143 
    144     typeset -g "${_bazel_cmd_options}"="${(pj:|:)option_list[*]}"
    145     _store_cache BAZEL_${lcmd}_options ${_bazel_cmd_options}
    146     typeset -g "${_bazel_cmd_args}"="${(pj:|:)cmd_args[*]}"
    147     _store_cache BAZEL_${lcmd}_args ${_bazel_cmd_args}
    148   fi
    149 }
    150 
    151 _get_build_targets() {
    152   local pkg=$1
    153   local rule_re
    154   typeset -a completions
    155   case $target_type in
    156     test)
    157       rule_re=".*_test"
    158       ;;
    159     build)
    160       rule_re=".*"
    161       ;;
    162     bin)
    163       rule_re=".*_test|.*_binary"
    164       ;;
    165   esac
    166   completions=(${$(_bazel_b query "kind(\"${rule_re}\", ${pkg}:all)" 2>/dev/null)##*:})
    167   if ( (( ${#completions} > 0 )) && [[ $target_type != bin ]] ); then
    168     completions+=(all)
    169   fi
    170   echo ${completions[*]}
    171 }
    172 
    173 # Returns all packages that match $PREFIX.  PREFIX may start with //, in which
    174 # case the workspace roots are searched.  Otherwise, they are completed based on
    175 # PWD.
    176 _get_build_packages() {
    177   local workspace pfx
    178   typeset -a package_roots paths final_paths
    179   workspace=$PWD
    180   package_roots=(${(ps.:.)BAZEL_COMPLETION_PACKAGE_PATH})
    181   package_roots=(${^package_roots//\%workspace\%/$workspace})
    182   if [[ "${(e)PREFIX}" == //* ]]; then
    183     pfx=${(e)PREFIX[2,-1]}
    184   else
    185     pfx=${(e)PREFIX}
    186   fi
    187   paths=(${^package_roots}/${pfx}*(/))
    188   for p in ${paths[*]}; do
    189     if [[ -f ${p}/BUILD || -f ${p}/BUILD.bazel ]]; then
    190       final_paths+=(${p##*/}:)
    191     fi
    192     final_paths+=(${p##*/}/)
    193   done
    194   echo ${final_paths[*]}
    195 }
    196 
    197 _package_remove_slash() {
    198   if [[ $KEYS == ':' && $LBUFFER == */ ]]; then
    199     LBUFFER=${LBUFFER[1,-2]}
    200   fi
    201 }
    202 
    203 # Completion function for BUILD targets, called by the completion system.
    204 _bazel_complete_target() {
    205   local expl
    206   typeset -a packages targets
    207   if [[ "${(e)PREFIX}" != *:* ]]; then
    208     # There is no : in the prefix, completion can be either
    209     # a package or a target, if the cwd is a package itself.
    210     if [[ -f $PWD/BUILD || -f $PWD/BUILD.bazel ]]; then
    211       targets=($(_get_build_targets ""))
    212       _description build_target expl "BUILD target"
    213       compadd "${expl[@]}" -a targets
    214     fi
    215     packages=($(_get_build_packages))
    216     _description build_package expl "BUILD package"
    217     # Chop of the leading path segments from the prefix for display.
    218     compset -P '*/'
    219     compadd -R _package_remove_slash -S '' "${expl[@]}" -a packages
    220   else
    221     targets=($(_get_build_targets "${${(e)PREFIX}%:*}"))
    222     _description build_target expl "BUILD target"
    223     # Ignore the current prefix for the upcoming completion, since we only list
    224     # the names of the targets, not the full path.
    225     compset -P '*:'
    226     compadd "${expl[@]}" -a targets
    227   fi
    228 }
    229 
    230 _bazel_complete_target_label() {
    231   typeset -g target_type=build
    232   _bazel_complete_target
    233 }
    234 
    235 _bazel_complete_target_label_test() {
    236   typeset -g target_type=test
    237   _bazel_complete_target
    238 }
    239 
    240 _bazel_complete_target_label_bin() {
    241   typeset -g target_type=bin
    242   _bazel_complete_target
    243 }
    244 
    245 ### Actual completion commands
    246 
    247 _bazel() {
    248   _adapt_subcommand_offset
    249   if (( CURRENT - OFFSET > 0 )); then
    250     # Remember the subcommand name, stored globally so we can access it
    251     # from any subsequent function
    252     cmd=${words[OFFSET]//-/_}
    253 
    254     # Set the context for the subcommand.
    255     curcontext="${curcontext%:*:*}:bazel-$cmd:"
    256     _set_cache_policy
    257 
    258     # Narrow the range of words we are looking at to exclude cmd
    259     # name and any leading options
    260     (( CURRENT = CURRENT - OFFSET + 1 ))
    261     shift $((OFFSET - 1)) words
    262     # Run the completion for the subcommand
    263     _bazel_get_options $cmd
    264     _arguments : \
    265       ${(Pps:|:)_bazel_cmd_options} \
    266       ${(Pps:|:)_bazel_cmd_args}
    267   else
    268     _set_cache_policy
    269     # Start special handling for global options,
    270     # which can be retrieved by calling
    271     # $ bazel help startup_options
    272     _bazel_get_options startup_options
    273     _arguments : \
    274       ${(Pps:|:)_bazel_cmd_options} \
    275       "*:commands:_bazel_commands"
    276   fi
    277   return
    278 }
    279 
    280 _get_commands() {
    281   # bazel_cmd_list is a global (g) array (a)
    282   typeset -ga _bazel_cmd_list
    283   # Use `bazel help` instead of `bazel help completion` to get command
    284   # descriptions.
    285   if _bazel_cmd_list=("${(@f)$(_bazel_b help | awk '
    286 /Available commands/ { command=1; }
    287 /  [-a-z]+[ \t]+.+/ { if (command) { printf "%s:", $1; for (i=2; i<=NF; i++) printf "%s ", $i; print "" } }
    288 /^$/ { command=0; }')}"); then
    289     _store_cache BAZEL_commands _bazel_cmd_list
    290   fi
    291 }
    292 
    293 # Completion function for bazel subcommands, called by the completion system.
    294 _bazel_commands() {
    295   if [[ ${#_bazel_cmd_list} == 0 ]]; then
    296     if _cache_invalid BAZEL_commands \
    297       || ! _bazel_safe_retrieve_cache BAZEL_commands _bazel_cmd_list; then
    298       _get_commands
    299     fi
    300   fi
    301 
    302   _describe -t bazel-commands 'Bazel command' _bazel_cmd_list
    303 }
    304 
    305 # Completion function for bazel help options, called by the completion system.
    306 _bazel_help_topic() {
    307   if [[ ${#_bazel_cmd_list} == 0 ]]; then
    308     if _cache_invalid BAZEL_commands \
    309       || ! _bazel_safe_retrieve_cache BAZEL_commands _bazel_cmd_list; then
    310       _get_commands
    311     fi
    312   fi
    313 
    314   while [[ $# -gt 0 ]]; do
    315     if [[ $1 == -- ]]; then
    316       shift
    317       break
    318     fi
    319     shift
    320   done
    321   _bazel_help_list=($@)
    322   _bazel_help_list+=($_bazel_cmd_list)
    323   _describe -t bazel-help 'Help topic' _bazel_help_list
    324 }
    325 
    326 # Completion function for bazel info keys, called by the completion system.
    327 _bazel_info_key() {
    328   if [[ ${#_bazel_info_keys_list} == 0 ]]; then
    329     if _cache_invalid BAZEL_info_keys \
    330       || ! _bazel_safe_retrieve_cache BAZEL_info_keys _bazel_info_keys_list; then
    331       typeset -ga _bazel_info_keys_list
    332       # Use `bazel help` instead of `bazel help completion` to get info-key
    333       # descriptions.
    334       if _bazel_info_keys_list=("${(@f)$(_bazel_b help info-keys | awk '
    335   { printf "%s:", $1; for (i=2; i<=NF; i++) printf "%s ", $i; print "" }')}"); then
    336         _store_cache BAZEL_info_keys _bazel_info_keys_list
    337       fi
    338     fi
    339   fi
    340   _describe -t bazel-info 'Key' _bazel_info_keys_list
    341 }