# /* vim: set ai ts=4 ft=sh: */ # # Copyright 2011, The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # _adb() { unset -v have type $1 &> /dev/null && have="yes" if [ "$have" != "yes" ]; then return fi local where i cur serial COMPREPLY=() serial="${ANDROID_SERIAL:-none}" where=OPTIONS for ((i=1; i <= COMP_CWORD; i++)); do cur="${COMP_WORDS[i]}" case "${cur}" in -s) where=OPT_SERIAL ;; -p) where=OPT_PATH ;; -*) where=OPTIONS ;; *) if [[ $where == OPT_SERIAL ]]; then where=OPT_SERIAL_ARG elif [[ $where == OPT_SERIAL_ARG ]]; then serial=${cur} where=OPTIONS else where=COMMAND break fi ;; esac done if [[ $where == COMMAND && $i -ge $COMP_CWORD ]]; then where=OPTIONS fi OPTIONS="-d -e -s -p" COMMAND="devices connect disconnect push pull sync shell emu logcat lolcat forward jdwp install uninstall bugreport help version start-server kill-server get-state get-serialno status-window remount reboot reboot-bootloader root usb tcpip disable-verity" case $where in OPTIONS|OPT_SERIAL|OPT_PATH) COMPREPLY=( $(compgen -W "$OPTIONS $COMMAND" -- "$cur") ) ;; OPT_SERIAL_ARG) local devices=$(command adb devices 2> /dev/null | grep -v "List of devices" | awk '{ print $1 }') COMPREPLY=( $(compgen -W "${devices}" -- ${cur}) ) ;; COMMAND) if [[ $i -eq $COMP_CWORD ]]; then COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") ) else i=$((i+1)) case "${cur}" in install) _adb_cmd_install "$serial" $i ;; sideload) _adb_cmd_sideload "$serial" $i ;; pull) _adb_cmd_pull "$serial" $i ;; push) _adb_cmd_push "$serial" $i ;; reboot) if [[ $COMP_CWORD == $i ]]; then args="bootloader recovery" COMPREPLY=( $(compgen -W "${args}" -- "${COMP_WORDS[i]}") ) fi ;; shell) _adb_cmd_shell "$serial" $i ;; uninstall) _adb_cmd_uninstall "$serial" $i ;; esac fi ;; esac return 0 } _adb_cmd_install() { local serial i cur where serial=$1 i=$2 where=OPTIONS for ((; i <= COMP_CWORD; i++)); do cur="${COMP_WORDS[i]}" case "${cur}" in -*) where=OPTIONS ;; *) where=FILE break ;; esac done cur="${COMP_WORDS[COMP_CWORD]}" if [[ $where == OPTIONS ]]; then COMPREPLY=( $(compgen -W "-d -l -r -s" -- "${cur}") ) return fi _adb_util_complete_local_file "${cur}" '!*.apk' } _adb_cmd_sideload() { local serial i cur serial=$1 i=$2 cur="${COMP_WORDS[COMP_CWORD]}" _adb_util_complete_local_file "${cur}" '!*.zip' } _adb_cmd_push() { local serial IFS=$'\n' i cur serial=$1 i=$2 cur="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == $i ]]; then _adb_util_complete_local_file "${cur}" elif [[ $COMP_CWORD == $(($i+1)) ]]; then if [ "${cur}" == "" ]; then cur="/" fi _adb_util_list_files $serial "${cur}" fi } _adb_cmd_pull() { local serial IFS=$'\n' i cur serial=$1 i=$2 cur="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == $i ]]; then if [ "${cur}" == "" ]; then cur="/" fi _adb_util_list_files $serial "${cur}" elif [[ $COMP_CWORD == $(($i+1)) ]]; then _adb_util_complete_local_file "${cur}" fi } _adb_cmd_shell() { local serial IFS=$'\n' i cur local -a args serial=$1 i=$2 cur="${COMP_WORDS[i]}" if [ "$serial" != "none" ]; then args=(-s $serial) fi if [[ $i -eq $COMP_CWORD && ${cur:0:1} != "/" ]]; then paths=$(command adb ${args[@]} shell echo '$'PATH 2> /dev/null | tr -d '\r' | tr : '\n') COMMAND=$(command adb ${args[@]} shell ls $paths '2>' /dev/null | tr -d '\r' | { while read -r tmp; do command=${tmp##*/} printf '%s\n' "$command" done }) COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") ) return 0 fi i=$((i+1)) case "$cur" in ls) _adb_shell_ls $serial $i ;; /*) _adb_util_list_files $serial "$cur" ;; *) COMPREPLY=( ) ;; esac return 0 } _adb_cmd_uninstall() { local serial i where cur packages serial=$1 i=$2 if [ "$serial" != "none" ]; then args=(-s $serial) fi where=OPTIONS for ((; i <= COMP_CWORD; i++)); do cur="${COMP_WORDS[i]}" case "${cur}" in -*) where=OPTIONS ;; *) where=FILE break ;; esac done cur="${COMP_WORDS[COMP_CWORD]}" if [[ $where == OPTIONS ]]; then COMPREPLY=( $(compgen -W "-k" -- "${cur}") ) fi packages="$( command adb ${args[@]} shell pm list packages '2>' /dev/null 2> /dev/null | tr -d '\r' | { while read -r tmp; do local package=${tmp#package:} echo -n "${package} " done } )" COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${packages}" -- "${cur}") ) } _adb_shell_ls() { local serial i cur file local -a args serial=$1 i=$2 if [ "$serial" != "none" ]; then args=(-s $serial) fi where=OPTIONS for ((; i <= COMP_CWORD; i++)); do cur="${COMP_WORDS[i]}" case "${cur}" in -*) where=OPTIONS ;; *) where=FILE break ;; esac done file="${COMP_WORDS[COMP_CWORD]}" if [[ ${file} == "" ]]; then file="/" fi case $where in OPTIONS) COMPREPLY=( $(compgen -W "$OPTIONS" -- "$cur") ) _adb_util_list_files $serial "$file" ;; FILE) _adb_util_list_files $serial "$file" ;; esac return 0 } _adb_util_list_files() { local serial dir IFS=$'\n' local -a toks local -a args serial="$1" file="$2" if [ "$serial" != "none" ]; then args=(-s $serial) fi toks=( ${toks[@]-} $( command adb ${args[@]} shell ls -dF ${file}"*" '2>' /dev/null 2> /dev/null | tr -d '\r' | { while read -r tmp; do filetype=${tmp%% *} filename=${tmp:${#filetype}+1} if [[ ${filetype:${#filetype}-1:1} == d ]]; then printf '%s/\n' "$filename" else printf '%s\n' "$filename" fi done } )) # Since we're probably doing file completion here, don't add a space after. if [[ $(type -t compopt) = "builtin" ]]; then compopt -o nospace fi COMPREPLY=( ${COMPREPLY[@]:-} "${toks[@]}" ) } _adb_util_complete_local_file() { local file xspec i j IFS=$'\n' local -a dirs files file=$1 xspec=$2 # Since we're probably doing file completion here, don't add a space after. if [[ $(type -t compopt) = "builtin" ]]; then compopt -o plusdirs if [[ "${xspec}" == "" ]]; then COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") ) else compopt +o filenames COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") ) fi else # Work-around for shells with no compopt dirs=( $(compgen -d -- "${cur}" ) ) if [[ "${xspec}" == "" ]]; then files=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") ) else files=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") ) fi COMPREPLY=( $( for i in "${files[@]}"; do local skip= for j in "${dirs[@]}"; do if [[ $i == $j ]]; then skip=1 break fi done [[ -n $skip ]] || printf "%s\n" "$i" done )) COMPREPLY=( ${COMPREPLY[@]:-} $( for i in "${dirs[@]}"; do printf "%s/\n" "$i" done )) fi } if [[ $(type -t compopt) = "builtin" ]]; then complete -F _adb adb else complete -o nospace -F _adb adb fi