Home | History | Annotate | Download | only in bash_completion
      1 # /* vim: set ai ts=4 ft=sh: */
      2 #
      3 # Copyright 2011, The Android Open Source Project
      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 
     18 _adb() {
     19     if ! type -t "$1" >/dev/null; then
     20         return
     21     fi
     22 
     23     if type -t _init_completion >/dev/null; then
     24         _init_completion || return
     25     fi
     26 
     27     local where i cur serial
     28     COMPREPLY=()
     29 
     30     serial="${ANDROID_SERIAL:-none}"
     31     where=OPTIONS
     32     for ((i=1; i <= COMP_CWORD; i++)); do
     33         cur="${COMP_WORDS[i]}"
     34         case "${cur}" in
     35             -s)
     36                 where=OPT_SERIAL
     37                 ;;
     38             -p)
     39                 where=OPT_PATH
     40                 ;;
     41             -*)
     42                 where=OPTIONS
     43                 ;;
     44             *)
     45                 if [[ $where == OPT_SERIAL ]]; then
     46                     where=OPT_SERIAL_ARG
     47                     serial=${cur}
     48                 else
     49                     where=COMMAND
     50                     break
     51                 fi
     52                 ;;
     53         esac
     54     done
     55 
     56     if [[ $where == COMMAND && $i -ge $COMP_CWORD ]]; then
     57         where=OPTIONS
     58     fi
     59 
     60     OPTIONS="-d -e -s -p"
     61     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"
     62 
     63     case $where in
     64         OPTIONS|OPT_SERIAL|OPT_PATH)
     65             COMPREPLY=( $(compgen -W "$OPTIONS $COMMAND" -- "$cur") )
     66             ;;
     67         OPT_SERIAL_ARG)
     68             local devices=$(command adb devices 2> /dev/null | grep -v "List of devices" | awk '{ print $1 }')
     69             COMPREPLY=( $(compgen -W "${devices}" -- ${cur}) )
     70             ;;
     71         COMMAND)
     72             if [[ $i -eq $COMP_CWORD ]]; then
     73                 COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") )
     74             else
     75                 i=$((i+1))
     76                 case "${cur}" in
     77                     install)
     78                         _adb_cmd_install "$serial" $i
     79                         ;;
     80                     sideload)
     81                         _adb_cmd_sideload "$serial" $i
     82                         ;;
     83                     pull)
     84                         _adb_cmd_pull "$serial" $i
     85                         ;;
     86                     push)
     87                         _adb_cmd_push "$serial" $i
     88                         ;;
     89                     reboot)
     90                         if [[ $COMP_CWORD == $i ]]; then
     91                             args="bootloader recovery"
     92                             COMPREPLY=( $(compgen -W "${args}" -- "${COMP_WORDS[i]}") )
     93                         fi
     94                         ;;
     95                     shell)
     96                         _adb_cmd_shell "$serial" $i
     97                         ;;
     98                     uninstall)
     99                         _adb_cmd_uninstall "$serial" $i
    100                         ;;
    101                 esac
    102             fi
    103             ;;
    104     esac
    105 
    106     return 0
    107 }
    108 
    109 _adb_cmd_install() {
    110     local serial i cur where
    111 
    112     serial=$1
    113     i=$2
    114 
    115     where=OPTIONS
    116     for ((; i <= COMP_CWORD; i++)); do
    117         cur="${COMP_WORDS[i]}"
    118         case "${cur}" in
    119             -*)
    120                 where=OPTIONS
    121                 ;;
    122             *)
    123                 where=FILE
    124                 break
    125                 ;;
    126         esac
    127     done
    128 
    129     cur="${COMP_WORDS[COMP_CWORD]}"
    130     if [[ $where == OPTIONS ]]; then
    131         COMPREPLY=( $(compgen -W "-d -l -r -s" -- "${cur}") )
    132         return
    133     fi
    134 
    135     _adb_util_complete_local_file "${cur}" '!*.apk'
    136 }
    137 
    138 _adb_cmd_sideload() {
    139     local serial i cur
    140 
    141     serial=$1
    142     i=$2
    143 
    144     cur="${COMP_WORDS[COMP_CWORD]}"
    145 
    146     _adb_util_complete_local_file "${cur}" '!*.zip'
    147 }
    148 
    149 _adb_cmd_push() {
    150     local serial IFS=$'\n' i cur
    151 
    152     serial=$1
    153     i=$2
    154 
    155     cur="${COMP_WORDS[COMP_CWORD]}"
    156 
    157     if [[ $COMP_CWORD == $i ]]; then
    158         _adb_util_complete_local_file "${cur}"
    159     elif [[ $COMP_CWORD == $(($i+1)) ]]; then
    160         if [ "${cur}" == "" ]; then
    161             cur="/"
    162         fi
    163         _adb_util_list_files $serial "${cur}"
    164     fi
    165 }
    166 
    167 _adb_cmd_pull() {
    168     local serial IFS=$'\n' i cur
    169 
    170     serial=$1
    171     i=$2
    172 
    173     cur="${COMP_WORDS[COMP_CWORD]}"
    174 
    175     if [[ $COMP_CWORD == $i ]]; then
    176         if [ "${cur}" == "" ]; then
    177             cur="/"
    178         fi
    179         _adb_util_list_files $serial "${cur}"
    180     elif [[ $COMP_CWORD == $(($i+1)) ]]; then
    181         _adb_util_complete_local_file "${cur}"
    182     fi
    183 }
    184 
    185 _adb_cmd_shell() {
    186     local serial IFS=$'\n' i cur
    187     local -a args
    188 
    189     serial=$1
    190     i=$2
    191 
    192     cur="${COMP_WORDS[i]}"
    193     if [ "$serial" != "none" ]; then
    194         args=(-s $serial)
    195     fi
    196 
    197     if [[ $i -eq $COMP_CWORD && ${cur:0:1} != "/" ]]; then
    198         paths=$(command adb ${args[@]} shell echo '$'PATH 2> /dev/null | tr -d '\r' | tr : '\n')
    199         COMMAND=$(command adb ${args[@]} shell ls $paths '2>' /dev/null | tr -d '\r' | {
    200             while read -r tmp; do
    201                 command=${tmp##*/}
    202                 printf '%s\n' "$command"
    203             done
    204         })
    205         COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") )
    206         return 0
    207     fi
    208 
    209     i=$((i+1))
    210     case "$cur" in
    211         ls)
    212             _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"
    213             ;;
    214         cat)
    215             _adb_shell_file_command $serial $i "-h -e -t -u -v"
    216             ;;
    217         dumpsys)
    218             _adb_cmd_shell_dumpsys "$serial" $i
    219             ;;
    220         am)
    221             _adb_cmd_shell_am "$serial" $i
    222             ;;
    223         pm)
    224             _adb_cmd_shell_pm "$serial" $i
    225             ;;
    226         /*)
    227             _adb_util_list_files $serial "$cur"
    228             ;;
    229         *)
    230             COMPREPLY=( )
    231             ;;
    232     esac
    233 
    234     return 0
    235 }
    236 
    237 _adb_cmd_shell_dumpsys() {
    238     local serial i cur
    239     local -a args
    240     local candidates
    241 
    242     unset IFS
    243 
    244     serial=$1
    245     i=$2
    246 
    247     if [ "$serial" != "none" ]; then
    248         args=(-s $serial)
    249     fi
    250 
    251     if (( $i == $COMP_CWORD )) ; then
    252         cur="${COMP_WORDS[COMP_CWORD]}"
    253         # First line is a header, so need "1d".
    254         candidates=$(command adb ${args[@]} shell dumpsys -l 2> /dev/null | sed -e '1d;s/^  *//' | tr -d '\r')
    255         candidates="-l $candidates"
    256         COMPREPLY=( $(compgen -W "$candidates" -- "$cur") )
    257         return 0
    258     fi
    259 
    260     COMPREPLY=( )
    261     return 0
    262 }
    263 
    264 _adb_cmd_shell_am() {
    265     local serial i cur
    266     local candidates
    267 
    268     unset IFS
    269 
    270     serial=$1
    271     i=$2
    272 
    273     if (( $i == $COMP_CWORD )) ; then
    274         cur="${COMP_WORDS[COMP_CWORD]}"
    275         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"
    276         COMPREPLY=( $(compgen -W "$candidates" -- "$cur") )
    277         return 0
    278     fi
    279 
    280     COMPREPLY=( )
    281     return 0
    282 }
    283 
    284 
    285 _adb_cmd_shell_pm() {
    286     local serial i cur
    287     local candidates
    288 
    289     unset IFS
    290 
    291     serial=$1
    292     i=$2
    293 
    294     if (( $i == $COMP_CWORD )) ; then
    295         cur="${COMP_WORDS[COMP_CWORD]}"
    296         candidates="-l -lf -p clear create-user default-state disable disable-until-used disable-user dump enable get-app-link get-install-location get-max-users grant hide install install-abandon install-commit install-create install-write list move-package move-primary-storage path remove-user reset-permissions revoke set-app-link set-installer set-install-location set-permission-enforced trim-caches unhide uninstall"
    297         COMPREPLY=( $(compgen -W "$candidates" -- "$cur") )
    298         return 0
    299     fi
    300 
    301     if (( $i + 1 == $COMP_CWORD )) && [[ "${COMP_WORDS[COMP_CWORD -1]}" == "list" ]]  ; then
    302         cur="${COMP_WORDS[COMP_CWORD]}"
    303         candidates="packages permission-groups permissions instrumentation features libraries users"
    304         COMPREPLY=( $(compgen -W "$candidates" -- "$cur") )
    305         return 0
    306     fi
    307 
    308     COMPREPLY=( )
    309     return 0
    310 }
    311 
    312 _adb_cmd_uninstall() {
    313     local serial i where cur packages
    314 
    315     serial=$1
    316     i=$2
    317     if [ "$serial" != "none" ]; then
    318         args=(-s $serial)
    319     fi
    320 
    321     where=OPTIONS
    322     for ((; i <= COMP_CWORD; i++)); do
    323         cur="${COMP_WORDS[i]}"
    324         case "${cur}" in
    325             -*)
    326                 where=OPTIONS
    327                 ;;
    328             *)
    329                 where=FILE
    330                 break
    331                 ;;
    332         esac
    333     done
    334 
    335     cur="${COMP_WORDS[COMP_CWORD]}"
    336     if [[ $where == OPTIONS ]]; then
    337         COMPREPLY=( $(compgen -W "-k" -- "${cur}") )
    338     fi
    339 
    340     packages="$(
    341         command adb ${args[@]} shell pm list packages '2>' /dev/null 2> /dev/null | tr -d '\r' | {
    342             while read -r tmp; do
    343                 local package=${tmp#package:}
    344                 echo -n "${package} "
    345             done
    346         }
    347     )"
    348 
    349     COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${packages}" -- "${cur}") )
    350 }
    351 
    352 _adb_shell_file_command() {
    353     local serial i cur file options
    354     local -a args
    355 
    356     serial=$1
    357     i=$2
    358     if [ "$serial" != "none" ]; then
    359         args=(-s $serial)
    360     fi
    361     options=$3
    362 
    363     where=OPTIONS
    364     for ((; i <= COMP_CWORD; i++)); do
    365         cur="${COMP_WORDS[i]}"
    366         case "${cur}" in
    367             -*)
    368                 where=OPTIONS
    369                 ;;
    370             *)
    371                 where=FILE
    372                 break
    373                 ;;
    374         esac
    375     done
    376 
    377     file="${COMP_WORDS[COMP_CWORD]}"
    378     if [[ ${file} == "" ]]; then
    379         file="/"
    380     fi
    381 
    382     case $where in
    383         OPTIONS)
    384             unset IFS
    385             COMPREPLY=( $(compgen -W "$options" -- "$cur") )
    386             ;;
    387         FILE)
    388             _adb_util_list_files $serial "$file"
    389             ;;
    390     esac
    391 
    392     return 0
    393 }
    394 
    395 _adb_util_list_files() {
    396     local serial dir IFS=$'\n'
    397     local -a toks
    398     local -a args
    399 
    400     serial="$1"
    401     file="$2"
    402 
    403     if [ "$serial" != "none" ]; then
    404         args=(-s $serial)
    405     fi
    406 
    407     if [[ $( command adb ${args[@]} shell ls -dF / '2>/dev/null' | tr -d '\r' ) == "d /" ]] ; then
    408         toks=( ${toks[@]-} $(
    409             command adb ${args[@]} shell ls -dF ${file}"*" '2>' /dev/null 2> /dev/null | tr -d '\r' | {
    410                 while read -r tmp; do
    411                     filetype=${tmp%% *}
    412                     filename=${tmp:${#filetype}+1}
    413                     if [[ ${filetype:${#filetype}-1:1} == d ]]; then
    414                         printf '%s/\n' "$filename"
    415                     else
    416                         printf '%s\n' "$filename"
    417                     fi
    418                 done
    419             }
    420         ))
    421     else
    422         toks=( ${toks[@]-} $(
    423             command adb ${args[@]} shell ls -dp ${file}"*" '2>/dev/null' 2> /dev/null | tr -d '\r'
    424         ))
    425     fi
    426 
    427     # Since we're probably doing file completion here, don't add a space after.
    428     if [[ $(type -t compopt) = "builtin" ]]; then
    429         compopt -o nospace
    430     fi
    431 
    432     COMPREPLY=( ${COMPREPLY[@]:-} "${toks[@]}" )
    433 }
    434 
    435 _adb_util_complete_local_file()
    436 {
    437     local file xspec i j IFS=$'\n'
    438     local -a dirs files
    439 
    440     file=$1
    441     xspec=$2
    442 
    443     # Since we're probably doing file completion here, don't add a space after.
    444     if [[ $(type -t compopt) = "builtin" ]]; then
    445         compopt -o plusdirs
    446         if [[ "${xspec}" == "" ]]; then
    447             COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") )
    448         else
    449             compopt +o filenames
    450             COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") )
    451         fi
    452     else
    453         # Work-around for shells with no compopt
    454 
    455         dirs=( $(compgen -d -- "${cur}" ) )
    456 
    457         if [[ "${xspec}" == "" ]]; then
    458             files=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") )
    459         else
    460             files=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") )
    461         fi
    462 
    463         COMPREPLY=( $(
    464             for i in "${files[@]}"; do
    465                 local skip=
    466                 for j in "${dirs[@]}"; do
    467                     if [[ $i == $j ]]; then
    468                         skip=1
    469                         break
    470                     fi
    471                 done
    472                 [[ -n $skip ]] || printf "%s\n" "$i"
    473             done
    474         ))
    475 
    476         COMPREPLY=( ${COMPREPLY[@]:-} $(
    477             for i in "${dirs[@]}"; do
    478                 printf "%s/\n" "$i"
    479             done
    480         ))
    481     fi
    482 }
    483 
    484 
    485 if [[ $(type -t compopt) = "builtin" ]]; then
    486     complete -F _adb adb
    487 else
    488     complete -o nospace -F _adb adb
    489 fi
    490