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"
    297         candidates+=" disable-until-used disable-user dump enable"
    298         candidates+=" get-app-link get-install-location get-max-users"
    299         candidates+=" get-max-running-users grant hide install"
    300         candidates+=" install-abandon install-commit install-create"
    301         candidates+=" install-write list move-package"
    302         candidates+=" move-primary-storage path remove-user"
    303         candidates+=" reset-permissions revoke set-app-link"
    304         candidates+=" set-installer set-install-location"
    305         candidates+=" set-permission-enforced trim-caches unhide"
    306         candidates+=" uninstall"
    307         COMPREPLY=( $(compgen -W "$candidates" -- "$cur") )
    308         return 0
    309     fi
    310 
    311     if (( $i + 1 == $COMP_CWORD )) && [[ "${COMP_WORDS[COMP_CWORD -1]}" == "list" ]]  ; then
    312         cur="${COMP_WORDS[COMP_CWORD]}"
    313         candidates="packages permission-groups permissions instrumentation features libraries users"
    314         COMPREPLY=( $(compgen -W "$candidates" -- "$cur") )
    315         return 0
    316     fi
    317 
    318     COMPREPLY=( )
    319     return 0
    320 }
    321 
    322 _adb_cmd_uninstall() {
    323     local serial i where cur packages
    324 
    325     serial=$1
    326     i=$2
    327     if [ "$serial" != "none" ]; then
    328         args=(-s $serial)
    329     fi
    330 
    331     where=OPTIONS
    332     for ((; i <= COMP_CWORD; i++)); do
    333         cur="${COMP_WORDS[i]}"
    334         case "${cur}" in
    335             -*)
    336                 where=OPTIONS
    337                 ;;
    338             *)
    339                 where=FILE
    340                 break
    341                 ;;
    342         esac
    343     done
    344 
    345     cur="${COMP_WORDS[COMP_CWORD]}"
    346     if [[ $where == OPTIONS ]]; then
    347         COMPREPLY=( $(compgen -W "-k" -- "${cur}") )
    348     fi
    349 
    350     packages="$(
    351         command adb ${args[@]} shell pm list packages '2>' /dev/null 2> /dev/null | tr -d '\r' | {
    352             while read -r tmp; do
    353                 local package=${tmp#package:}
    354                 echo -n "${package} "
    355             done
    356         }
    357     )"
    358 
    359     COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${packages}" -- "${cur}") )
    360 }
    361 
    362 _adb_shell_file_command() {
    363     local serial i cur file options
    364     local -a args
    365 
    366     serial=$1
    367     i=$2
    368     if [ "$serial" != "none" ]; then
    369         args=(-s $serial)
    370     fi
    371     options=$3
    372 
    373     where=OPTIONS
    374     for ((; i <= COMP_CWORD; i++)); do
    375         cur="${COMP_WORDS[i]}"
    376         case "${cur}" in
    377             -*)
    378                 where=OPTIONS
    379                 ;;
    380             *)
    381                 where=FILE
    382                 break
    383                 ;;
    384         esac
    385     done
    386 
    387     file="${COMP_WORDS[COMP_CWORD]}"
    388     if [[ ${file} == "" ]]; then
    389         file="/"
    390     fi
    391 
    392     case $where in
    393         OPTIONS)
    394             unset IFS
    395             COMPREPLY=( $(compgen -W "$options" -- "$cur") )
    396             ;;
    397         FILE)
    398             _adb_util_list_files $serial "$file"
    399             ;;
    400     esac
    401 
    402     return 0
    403 }
    404 
    405 _adb_util_list_files() {
    406     local serial dir IFS=$'\n'
    407     local -a toks
    408     local -a args
    409 
    410     serial="$1"
    411     file="$2"
    412 
    413     if [ "$serial" != "none" ]; then
    414         args=(-s $serial)
    415     fi
    416 
    417     if [[ $( command adb ${args[@]} shell ls -dF / '2>/dev/null' | tr -d '\r' ) == "d /" ]] ; then
    418         toks=( ${toks[@]-} $(
    419             command adb ${args[@]} shell ls -dF ${file}"*" '2>' /dev/null 2> /dev/null | tr -d '\r' | {
    420                 while read -r tmp; do
    421                     filetype=${tmp%% *}
    422                     filename=${tmp:${#filetype}+1}
    423                     if [[ ${filetype:${#filetype}-1:1} == d ]]; then
    424                         printf '%s/\n' "$filename"
    425                     else
    426                         printf '%s\n' "$filename"
    427                     fi
    428                 done
    429             }
    430         ))
    431     else
    432         toks=( ${toks[@]-} $(
    433             command adb ${args[@]} shell ls -dp ${file}"*" '2>/dev/null' 2> /dev/null | tr -d '\r'
    434         ))
    435     fi
    436 
    437     # Since we're probably doing file completion here, don't add a space after.
    438     if [[ $(type -t compopt) = "builtin" ]]; then
    439         compopt -o nospace
    440     fi
    441 
    442     COMPREPLY=( ${COMPREPLY[@]:-} "${toks[@]}" )
    443 }
    444 
    445 _adb_util_complete_local_file()
    446 {
    447     local file xspec i j IFS=$'\n'
    448     local -a dirs files
    449 
    450     file=$1
    451     xspec=$2
    452 
    453     # Since we're probably doing file completion here, don't add a space after.
    454     if [[ $(type -t compopt) = "builtin" ]]; then
    455         compopt -o plusdirs
    456         if [[ "${xspec}" == "" ]]; then
    457             COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") )
    458         else
    459             compopt +o filenames
    460             COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") )
    461         fi
    462     else
    463         # Work-around for shells with no compopt
    464 
    465         dirs=( $(compgen -d -- "${cur}" ) )
    466 
    467         if [[ "${xspec}" == "" ]]; then
    468             files=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") )
    469         else
    470             files=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") )
    471         fi
    472 
    473         COMPREPLY=( $(
    474             for i in "${files[@]}"; do
    475                 local skip=
    476                 for j in "${dirs[@]}"; do
    477                     if [[ $i == $j ]]; then
    478                         skip=1
    479                         break
    480                     fi
    481                 done
    482                 [[ -n $skip ]] || printf "%s\n" "$i"
    483             done
    484         ))
    485 
    486         COMPREPLY=( ${COMPREPLY[@]:-} $(
    487             for i in "${dirs[@]}"; do
    488                 printf "%s/\n" "$i"
    489             done
    490         ))
    491     fi
    492 }
    493 
    494 
    495 if [[ $(type -t compopt) = "builtin" ]]; then
    496     complete -F _adb adb
    497 else
    498     complete -o nospace -F _adb adb
    499 fi
    500