| # /* 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() { | |
| if ! check_type "$1" >/dev/null; then | |
| return | |
| fi | |
| if check_type _init_completion >/dev/null; then | |
| _init_completion || 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 | |
| serial=${cur} | |
| 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_file_command $serial $i "--color -A -C -F -H -L -R -S -Z -a -c -d -f -h -i -k -l -m -n -p -q -r -s -t -u -x -1" | |
| ;; | |
| cat) | |
| _adb_shell_file_command $serial $i "-h -e -t -u -v" | |
| ;; | |
| dumpsys) | |
| _adb_cmd_shell_dumpsys "$serial" $i | |
| ;; | |
| am) | |
| _adb_cmd_shell_am "$serial" $i | |
| ;; | |
| pm) | |
| _adb_cmd_shell_pm "$serial" $i | |
| ;; | |
| /*) | |
| _adb_util_list_files $serial "$cur" | |
| ;; | |
| *) | |
| COMPREPLY=( ) | |
| ;; | |
| esac | |
| return 0 | |
| } | |
| _adb_cmd_shell_dumpsys() { | |
| local serial i cur | |
| local -a args | |
| local candidates | |
| unset IFS | |
| serial=$1 | |
| i=$2 | |
| if [ "$serial" != "none" ]; then | |
| args=(-s $serial) | |
| fi | |
| if (( $i == $COMP_CWORD )) ; then | |
| cur="${COMP_WORDS[COMP_CWORD]}" | |
| # First line is a header, so need "1d". | |
| candidates=$(command adb ${args[@]} shell dumpsys -l 2> /dev/null | sed -e '1d;s/^ *//' | tr -d '\r') | |
| candidates="-l $candidates" | |
| COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) | |
| return 0 | |
| fi | |
| COMPREPLY=( ) | |
| return 0 | |
| } | |
| _adb_cmd_shell_am() { | |
| local serial i cur | |
| local candidates | |
| unset IFS | |
| serial=$1 | |
| i=$2 | |
| if (( $i == $COMP_CWORD )) ; then | |
| cur="${COMP_WORDS[COMP_CWORD]}" | |
| candidates="broadcast clear-debug-app clear-watch-heap dumpheap force-stop get-config get-inactive hang idle-maintenance instrument kill kill-all monitor package-importance profile restart screen-compat send-trim-memory set-debug-app set-inactive set-watch-heap stack start startservice start-user stopservice stop-user suppress-resize-config-changes switch-user task to-app-uri to-intent-uri to-uri" | |
| COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) | |
| return 0 | |
| fi | |
| COMPREPLY=( ) | |
| return 0 | |
| } | |
| _adb_cmd_shell_pm() { | |
| local serial i cur | |
| local candidates | |
| unset IFS | |
| serial=$1 | |
| i=$2 | |
| if (( $i == $COMP_CWORD )) ; then | |
| cur="${COMP_WORDS[COMP_CWORD]}" | |
| candidates="-l -lf -p clear create-user default-state disable" | |
| candidates+=" disable-until-used disable-user dump enable" | |
| candidates+=" get-app-link get-install-location get-max-users" | |
| candidates+=" get-max-running-users grant hide install" | |
| candidates+=" install-abandon install-commit install-create" | |
| candidates+=" install-write list move-package" | |
| candidates+=" move-primary-storage path remove-user" | |
| candidates+=" reset-permissions revoke set-app-link" | |
| candidates+=" set-installer set-install-location" | |
| candidates+=" set-permission-enforced trim-caches unhide" | |
| candidates+=" uninstall" | |
| COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) | |
| return 0 | |
| fi | |
| if (( $i + 1 == $COMP_CWORD )) && [[ "${COMP_WORDS[COMP_CWORD -1]}" == "list" ]] ; then | |
| cur="${COMP_WORDS[COMP_CWORD]}" | |
| candidates="packages permission-groups permissions instrumentation features libraries users" | |
| COMPREPLY=( $(compgen -W "$candidates" -- "$cur") ) | |
| return 0 | |
| fi | |
| COMPREPLY=( ) | |
| 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_file_command() { | |
| local serial i cur file options | |
| local -a args | |
| serial=$1 | |
| i=$2 | |
| if [ "$serial" != "none" ]; then | |
| args=(-s $serial) | |
| fi | |
| options=$3 | |
| 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) | |
| unset IFS | |
| COMPREPLY=( $(compgen -W "$options" -- "$cur") ) | |
| ;; | |
| 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 | |
| if [[ $( command adb ${args[@]} shell ls -dF / '2>/dev/null' | tr -d '\r' ) == "d /" ]] ; then | |
| 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 | |
| } | |
| )) | |
| else | |
| toks=( ${toks[@]-} $( | |
| command adb ${args[@]} shell ls -dp ${file}"*" '2>/dev/null' 2> /dev/null | tr -d '\r' | |
| )) | |
| fi | |
| # Since we're probably doing file completion here, don't add a space after. | |
| if [[ $(check_type 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 [[ $(check_type 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 [[ $(check_type compopt) == "builtin" ]]; then | |
| complete -F _adb adb | |
| else | |
| complete -o nospace -F _adb adb | |
| fi |