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