# As this script must be sourced by shells to be useful, no practical #shebang is possible. # Note: must 'source' this file again in the terminal after any edits! _comp_builder() { # Does the file actually exist? If not, abort. local CMD_PATH=`readlink -f "$1"` if [ -z "${CMD_PATH}" ]; then exit 0 fi # Detect - is this a keyman repo? If not, exit early; we don't expect repo-external compatibility. local CMD_DIR="$(dirname "${CMD_PATH}")" cd "${CMD_DIR}" # Works correctly even if the directory has no backing repository. git remote get-url origin | grep -q 'github.com/keymanapp' || exit 0 # Some of the configuration differs when ZSH is the OS's primary terminal; this flag # may be used to tailor this function accordingly. local IS_ZSH=false if [ "${SHELL##*/}" = "zsh" ]; then IS_ZSH=true fi # Warning - zsh uses -A, not -a, for array-read operations! # This is 'sourced' by the shell profile script, so macOS zsh terminal # usage must be aware of this and adapt. local READ_ARRAY="-a" if [ $IS_ZSH = true ]; then READ_ARRAY="-A" fi # Is it actually a builder-script? If not, abort. If so, it defines # a special option used to provide us with completion-target data. local builder_params=`${CMD_PATH} --builder-completion-describe` || exit 0 local BASE_NAME=$(basename "$CMD_PATH") local BUILDER_ARG_STR="${COMP_LINE##*${BASE_NAME} }" local builder_args # Does not actually preserve an empty token at the end. read -r $READ_ARRAY builder_args <<< "${BUILDER_ARG_STR}" # Determine the current token (given the caret position) and # all existing, already-completed actions, targets, and options # for the script before the current token. local current_token= # If the caret is adjacent to non-whitespace - thus is editing # a builder argument... if [ ! -z "${COMP_WORDS[COMP_CWORD]}" ]; then # Then note the last token as the token being edited... current_token="${builder_args[-1]}" # ... and thus not pre-completed. unset builder_args[-1] fi # Parse the builder-description for completion target data. local action_str target_str option_str IFS=";" read -r action_str target_str option_str <<< "$builder_params" local actions targets options IFS=" " read -r $READ_ARRAY actions <<< "$action_str" IFS=" " read -r $READ_ARRAY targets <<< "$target_str" IFS=" " read -r $READ_ARRAY options <<< "$option_str" local action target if [[ $current_token =~ : ]]; then IFS=: read -r action target <<< "$current_token" target=:$target else action="$current_token" target= fi local all=() # If there is no $action component, it's a standalone target. if [[ -z "$action" ]] && [[ -z "$target" ]]; then all+="${actions[@]}" all+=" ${targets[@]}" all+=" ${options[@]}" COMPREPLY=( $(compgen -W "${all[@]}" -- "${current_token}") ) elif [[ -z "$action" ]]; then # It's an unpaired target. all="${targets[@]}" COMPREPLY=( $(compgen -W "${all[@]}" -- "${current_token}") ) if [ $IS_ZSH == false ]; then # bash doesn't handle completion with colons well; we should remove the # colon prefix from each entry. ZSH actually doesn't have this issue. local i for (( i=0; i<${#COMPREPLY[@]}; i++ )); do COMPREPLY[$i]="${COMPREPLY[$i]##*:}" done fi elif [[ -z "$target" ]]; then # It's an untargeted action or an option. all+="${actions[@]}" all+=" ${options[@]}" COMPREPLY=( $(compgen -W "${all[@]}" -- "${current_token}") ) else # Ah, an action-target pair. We have an existing action, so we only need to # complete the target part. # First, build up the list of legal paired tokens. local actiontargets=() for e in "${targets[@]}"; do actiontargets+=("${action}${e}") done # Now, complete from that. all+="${actiontargets[@]}" COMPREPLY=( $(compgen -W "${all[@]}" -- "${current_token}") ) if [ $IS_ZSH == false ]; then # bash doesn't handle completion with colons well; we should remove the # colon prefix from each entry. ZSH actually doesn't have this issue. local i for (( i=0; i<${#COMPREPLY[@]}; i++ )); do COMPREPLY[$i]="${COMPREPLY[$i]##*:}" done fi fi } # When this script is sourced by .bashrc or similar, this provides autocompletion for # builder scripts named build.sh and test.sh. complete -o bashdefault -F _comp_builder build.sh complete -o bashdefault -F _comp_builder test.sh