• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
378if [[ $(type -t compopt) = "builtin" ]]; then
379    complete -F _adb adb
380else
381    complete -o nospace -F _adb adb
382fi
383