# bash completion for java, javac and javadoc -*- shell-script -*- # available path elements completion _java_path() { cur=${cur##*:} _filedir '@(jar|zip)' } # exact classpath determination _java_find_classpath() { local i # search first in current options for (( i=1; i < cword; i++ )); do if [[ "${words[i]}" == -@(cp|classpath) ]]; then classpath=${words[i+1]} break fi done # default to environment [[ -z $classpath ]] && classpath=$CLASSPATH # default to current directory [[ -z $classpath ]] && classpath=. } # exact sourcepath determination _java_find_sourcepath() { local i # search first in current options for (( i=1; i < cword; i++ )); do if [[ "${words[i]}" == -sourcepath ]]; then sourcepath=${words[i+1]} break fi done # default to classpath if [[ -z $sourcepath ]]; then local classpath _java_find_classpath sourcepath=$classpath fi } # available classes completion _java_classes() { local classpath i # find which classpath to use _java_find_classpath # convert package syntax to path syntax cur=${cur//.//} # parse each classpath element for classes for i in ${classpath//:/ }; do if [[ "$i" == *.@(jar|zip) && -r $i ]]; then if type zipinfo &>/dev/null; then COMPREPLY+=( $( zipinfo -1 "$i" "$cur*" 2>/dev/null | \ command grep '^[^$]*\.class$' ) ) else COMPREPLY+=( $( jar tf "$i" "$cur" | \ command grep '^[^$]*\.class$' ) ) fi elif [[ -d $i ]]; then COMPREPLY+=( $( compgen -d -- "$i/$cur" | sed -e "s|^$i/\(.*\)|\1.|" ) $( compgen -f -X '!*.class' -- "$i/$cur" | \ sed -e '/\$/d' -e "s|^$i/||" ) ) [[ $COMPREPLY == *.class ]] || compopt -o nospace # FIXME: if we have foo.class and foo/, the completion # returns "foo/"... how to give precedence to files # over directories? fi done # remove class extension COMPREPLY=( ${COMPREPLY[@]%.class} ) # convert path syntax to package syntax COMPREPLY=( ${COMPREPLY[@]//\//.} ) } # available packages completion _java_packages() { local sourcepath i # find which sourcepath to use _java_find_sourcepath # convert package syntax to path syntax cur=${cur//.//} # parse each sourcepath element for packages for i in ${sourcepath//:/ }; do if [[ -d $i ]]; then COMPREPLY+=( $( command ls -F -d $i/$cur* 2>/dev/null | \ sed -e 's|^'$i'/||' ) ) fi done # keep only packages COMPREPLY=( $( tr " " "\n" <<<"${COMPREPLY[@]}" | command grep "/$" ) ) # remove packages extension COMPREPLY=( ${COMPREPLY[@]%/} ) # convert path syntax to package syntax cur=${COMPREPLY[@]//\//.} } # java completion # _java() { local cur prev words cword _init_completion -n : || return local i for ((i=1; i < $cword; i++)); do case ${words[$i]} in -cp|-classpath) ((i++)) # skip the classpath string. ;; -*) # this is an option, not a class/jarfile name. ;; *) # once we've seen a class, just do filename completion _filedir return 0 ;; esac done case $cur in # standard option completions -verbose:*) COMPREPLY=( $( compgen -W 'class gc jni' -- "${cur#*:}" ) ) return 0 ;; -javaagent:*) cur=${cur#*:} _filedir '@(jar|zip)' return 0 ;; -agentpath:*) cur=${cur#*:} _filedir so return 0 ;; # various non-standard option completions -splash:*) cur=${cur#*:} _filedir '@(gif|jp?(e)g|png)' return 0 ;; -Xbootclasspath*:*) _java_path return 0 ;; -Xcheck:*) COMPREPLY=( $( compgen -W 'jni' -- "${cur#*:}" ) ) return 0 ;; -Xgc:*) COMPREPLY=( $( compgen -W 'singlecon gencon singlepar genpar' \ -- "${cur#*:}" ) ) return 0 ;; -Xgcprio:*) COMPREPLY=( $( compgen -W 'throughput pausetime deterministic' \ -- "${cur#*:}" ) ) return 0 ;; -Xloggc:*|-Xverboselog:*) cur=${cur#*:} _filedir return 0 ;; -Xshare:*) COMPREPLY=( $( compgen -W 'auto off on' -- "${cur#*:}" ) ) return 0 ;; -Xverbose:*) COMPREPLY=( $( compgen -W 'memory load jni cpuinfo codegen opt gcpause gcreport' -- "${cur#*:}" ) ) return 0 ;; -Xverify:*) COMPREPLY=( $( compgen -W 'all none remote' -- "${cur#*:}" ) ) return 0 ;; # the rest that we have no completions for -D*|-*:*) return 0 ;; esac case $prev in -cp|-classpath) _java_path return 0 ;; esac if [[ "$cur" == -* ]]; then COMPREPLY=( $( compgen -W '$( _parse_help "$1" -help )' -- "$cur" ) ) [[ $cur == -X* ]] && \ COMPREPLY+=( $( compgen -W '$( _parse_help "$1" -X )' -- "$cur" ) ) else if [[ "$prev" == -jar ]]; then # jar file completion _filedir jar else # classes completion _java_classes fi fi [[ $COMPREPLY == -*[:=] ]] && compopt -o nospace __ltrim_colon_completions "$cur" } && complete -F _java java _javadoc() { local cur prev words cword _init_completion || return case $prev in -overview|-helpfile) _filedir '?(x)htm?(l)' return 0 ;; -stylesheetfile) _filedir css return 0 ;; -d|-link|-linkoffline) _filedir -d return 0 ;; -classpath|-bootclasspath|-docletpath|-sourcepath|-extdirs) _java_path return 0 ;; esac # -linkoffline takes two arguments if [[ $cword -gt 2 && ${words[$cword-2]} == -linkoffline ]]; then _filedir -d return fi if [[ "$cur" == -* ]]; then COMPREPLY=( $( compgen -W '$( _parse_help "$1" -help )' -- "$cur" ) ) else # source files completion _filedir java # packages completion _java_packages fi } && complete -F _javadoc javadoc _javac() { local cur prev words cword _init_completion -n : || return case $prev in -d) _filedir -d return 0 ;; -classpath|-bootclasspath|-sourcepath|-extdirs) _java_path return 0 ;; esac if [[ $cur == -+([a-zA-z0-9-_]):* ]]; then # Parse required options from -foo:{bar,quux,baz} local helpopt=-help [[ $cur == -X* ]] && helpopt=-X # For some reason there may be -g:none AND -g:{lines,source,vars}; # convert the none case to the curly brace format so it parses like # the others. local opts=$( "$1" $helpopt 2>&1 | sed -e 's/-g:none/-g:{none}/' -ne \ "s/^[[:space:]]*${cur%%:*}:{\([^}]\{1,\}\)}.*/\1/p" ) COMPREPLY=( $( compgen -W "${opts//,/ }" -- "${cur#*:}" ) ) return fi if [[ "$cur" == -* ]]; then COMPREPLY=( $( compgen -W '$( _parse_help "$1" -help )' -- "$cur" ) ) [[ $cur == -X* ]] && \ COMPREPLY+=( $( compgen -W '$( _parse_help "$1" -X )' -- "$cur" ) ) else # source files completion _filedir java fi [[ $COMPREPLY == -*[:=] ]] && compopt -o nospace __ltrim_colon_completions "$cur" } && complete -F _javac javac # ex: ts=4 sw=4 et filetype=sh