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 elif [[ $where == OPT_SERIAL_ARG ]]; then 47 serial=${cur} 48 where=OPTIONS 49 else 50 where=COMMAND 51 break 52 fi 53 ;; 54 esac 55 done 56 57 if [[ $where == COMMAND && $i -ge $COMP_CWORD ]]; then 58 where=OPTIONS 59 fi 60 61 OPTIONS="-d -e -s -p" 62 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" 63 64 case $where in 65 OPTIONS|OPT_SERIAL|OPT_PATH) 66 COMPREPLY=( $(compgen -W "$OPTIONS $COMMAND" -- "$cur") ) 67 ;; 68 OPT_SERIAL_ARG) 69 local devices=$(command adb devices 2> /dev/null | grep -v "List of devices" | awk '{ print $1 }') 70 COMPREPLY=( $(compgen -W "${devices}" -- ${cur}) ) 71 ;; 72 COMMAND) 73 if [[ $i -eq $COMP_CWORD ]]; then 74 COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") ) 75 else 76 i=$((i+1)) 77 case "${cur}" in 78 install) 79 _adb_cmd_install "$serial" $i 80 ;; 81 pull) 82 _adb_cmd_pull "$serial" $i 83 ;; 84 push) 85 _adb_cmd_push "$serial" $i 86 ;; 87 reboot) 88 if [[ $COMP_CWORD == $i ]]; then 89 args="bootloader recovery" 90 COMPREPLY=( $(compgen -W "${args}" -- "${COMP_WORDS[i]}") ) 91 fi 92 ;; 93 shell) 94 _adb_cmd_shell "$serial" $i 95 ;; 96 uninstall) 97 _adb_cmd_uninstall "$serial" $i 98 ;; 99 esac 100 fi 101 ;; 102 esac 103 104 return 0 105 } 106 107 _adb_cmd_install() { 108 local serial i cur where 109 110 serial=$1 111 i=$2 112 113 where=OPTIONS 114 for ((; i <= COMP_CWORD; i++)); do 115 cur="${COMP_WORDS[i]}" 116 case "${cur}" in 117 -*) 118 where=OPTIONS 119 ;; 120 *) 121 where=FILE 122 break 123 ;; 124 esac 125 done 126 127 cur="${COMP_WORDS[COMP_CWORD]}" 128 if [[ $where == OPTIONS ]]; then 129 COMPREPLY=( $(compgen -W "-l -r -s" -- "${cur}") ) 130 return 131 fi 132 133 _adb_util_complete_local_file "${cur}" '!*.apk' 134 } 135 136 _adb_cmd_push() { 137 local serial IFS=$'\n' i cur 138 139 serial=$1 140 i=$2 141 142 cur="${COMP_WORDS[COMP_CWORD]}" 143 144 if [[ $COMP_CWORD == $i ]]; then 145 _adb_util_complete_local_file "${cur}" 146 elif [[ $COMP_CWORD == $(($i+1)) ]]; then 147 if [ "${cur}" == "" ]; then 148 cur="/" 149 fi 150 _adb_util_list_files $serial "${cur}" 151 fi 152 } 153 154 _adb_cmd_pull() { 155 local serial IFS=$'\n' i cur 156 157 serial=$1 158 i=$2 159 160 cur="${COMP_WORDS[COMP_CWORD]}" 161 162 if [[ $COMP_CWORD == $i ]]; then 163 if [ "${cur}" == "" ]; then 164 cur="/" 165 fi 166 _adb_util_list_files $serial "${cur}" 167 elif [[ $COMP_CWORD == $(($i+1)) ]]; then 168 _adb_util_complete_local_file "${cur}" 169 fi 170 } 171 172 _adb_cmd_shell() { 173 local serial IFS=$'\n' i cur 174 local -a args 175 176 serial=$1 177 i=$2 178 179 cur="${COMP_WORDS[i]}" 180 if [ "$serial" != "none" ]; then 181 args=(-s $serial) 182 fi 183 184 if [[ $i -eq $COMP_CWORD && ${cur:0:1} != "/" ]]; then 185 paths=$(command adb ${args[@]} shell echo '$'PATH 2> /dev/null | tr -d '\r' | tr : '\n') 186 COMMAND=$(command adb ${args[@]} shell ls $paths '2>' /dev/null | tr -d '\r' | { 187 while read -r tmp; do 188 command=${tmp##*/} 189 printf '%s\n' "$command" 190 done 191 }) 192 COMPREPLY=( $(compgen -W "$COMMAND" -- "$cur") ) 193 return 0 194 fi 195 196 i=$((i+1)) 197 case "$cur" in 198 ls) 199 _adb_shell_ls $serial $i 200 ;; 201 /*) 202 _adb_util_list_files $serial "$cur" 203 ;; 204 *) 205 COMPREPLY=( ) 206 ;; 207 esac 208 209 return 0 210 } 211 212 _adb_cmd_uninstall() { 213 local serial i where cur packages 214 215 serial=$1 216 i=$2 217 if [ "$serial" != "none" ]; then 218 args=(-s $serial) 219 fi 220 221 where=OPTIONS 222 for ((; i <= COMP_CWORD; i++)); do 223 cur="${COMP_WORDS[i]}" 224 case "${cur}" in 225 -*) 226 where=OPTIONS 227 ;; 228 *) 229 where=FILE 230 break 231 ;; 232 esac 233 done 234 235 cur="${COMP_WORDS[COMP_CWORD]}" 236 if [[ $where == OPTIONS ]]; then 237 COMPREPLY=( $(compgen -W "-k" -- "${cur}") ) 238 fi 239 240 packages="$( 241 command adb ${args[@]} shell pm list packages '2>' /dev/null 2> /dev/null | tr -d '\r' | { 242 while read -r tmp; do 243 local package=${tmp#package:} 244 echo -n "${package} " 245 done 246 } 247 )" 248 249 COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -W "${packages}" -- "${cur}") ) 250 } 251 252 _adb_shell_ls() { 253 local serial i cur file 254 local -a args 255 256 serial=$1 257 i=$2 258 if [ "$serial" != "none" ]; then 259 args=(-s $serial) 260 fi 261 262 where=OPTIONS 263 for ((; i <= COMP_CWORD; i++)); do 264 cur="${COMP_WORDS[i]}" 265 case "${cur}" in 266 -*) 267 where=OPTIONS 268 ;; 269 *) 270 where=FILE 271 break 272 ;; 273 esac 274 done 275 276 file="${COMP_WORDS[COMP_CWORD]}" 277 if [[ ${file} == "" ]]; then 278 file="/" 279 fi 280 281 case $where in 282 OPTIONS) 283 COMPREPLY=( $(compgen -W "$OPTIONS" -- "$cur") ) 284 _adb_util_list_files $serial "$file" 285 ;; 286 FILE) 287 _adb_util_list_files $serial "$file" 288 ;; 289 esac 290 291 return 0 292 } 293 294 _adb_util_list_files() { 295 local serial dir IFS=$'\n' 296 local -a toks 297 local -a args 298 299 serial="$1" 300 file="$2" 301 302 if [ "$serial" != "none" ]; then 303 args=(-s $serial) 304 fi 305 306 toks=( ${toks[@]-} $( 307 command adb ${args[@]} shell ls -dF ${file}"*" '2>' /dev/null 2> /dev/null | tr -d '\r' | { 308 while read -r tmp; do 309 filetype=${tmp%% *} 310 filename=${tmp:${#filetype}+1} 311 if [[ ${filetype:${#filetype}-1:1} == d ]]; then 312 printf '%s/\n' "$filename" 313 else 314 printf '%s\n' "$filename" 315 fi 316 done 317 } 318 )) 319 320 # Since we're probably doing file completion here, don't add a space after. 321 if [[ $(type -t compopt) = "builtin" ]]; then 322 compopt -o nospace 323 fi 324 325 COMPREPLY=( ${COMPREPLY[@]:-} "${toks[@]}" ) 326 } 327 328 _adb_util_complete_local_file() 329 { 330 local file xspec i j 331 local -a dirs files 332 333 file=$1 334 xspec=$2 335 336 # Since we're probably doing file completion here, don't add a space after. 337 if [[ $(type -t compopt) = "builtin" ]]; then 338 compopt -o plusdirs 339 if [[ "${xspec}" == "" ]]; then 340 COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") ) 341 else 342 compopt +o filenames 343 COMPREPLY=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") ) 344 fi 345 else 346 # Work-around for shells with no compopt 347 348 dirs=( $(compgen -d -- "${cur}" ) ) 349 350 if [[ "${xspec}" == "" ]]; then 351 files=( ${COMPREPLY[@]:-} $(compgen -f -- "${cur}") ) 352 else 353 files=( ${COMPREPLY[@]:-} $(compgen -f -X "${xspec}" -- "${cur}") ) 354 fi 355 356 COMPREPLY=( $( 357 for i in "${files[@]}"; do 358 local skip= 359 for j in "${dirs[@]}"; do 360 if [[ $i == $j ]]; then 361 skip=1 362 break 363 fi 364 done 365 [[ -n $skip ]] || printf "%s\n" "$i" 366 done 367 )) 368 369 COMPREPLY=( ${COMPREPLY[@]:-} $( 370 for i in "${dirs[@]}"; do 371 printf "%s/\n" "$i" 372 done 373 )) 374 fi 375 } 376 377 378 if [[ $(type -t compopt) = "builtin" ]]; then 379 complete -F _adb adb 380 else 381 complete -o nospace -F _adb adb 382 fi 383