# 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 [[ ! -v 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 [[ ! -v 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$')) elif type unzip &>/dev/null; then # Last column, between entries consisting entirely of dashes COMPREPLY+=($(unzip -lq "$i" "$cur*" 2>/dev/null | awk '$NF ~ /^-+$/ { flag=!flag; next }; flag && $NF ~ /^[^$]*\.class/ { print $NF }')) elif type jar &>/dev/null; then COMPREPLY+=($(jar tf "$i" "$cur" | command grep '^[^$]*\.class$')) fi elif [[ -d $i ]]; then COMPREPLY+=( $(compgen -d -- "$i/$cur" | command sed -e "s|^$i/\(.*\)|\1.|") $(compgen -f -X '!*.class' -- "$i/$cur" | command 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 if ((${#COMPREPLY[@]} != 0)); then # remove class extension COMPREPLY=(${COMPREPLY[@]%.class}) # convert path syntax to package syntax COMPREPLY=(${COMPREPLY[@]//\//.}) fi } # 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 | command sed -e 's|^'$i'/||')) fi done if ((${#COMPREPLY[@]} != 0)); then # keep only packages COMPREPLY=($(tr " " "\n" <<<"${COMPREPLY[@]}" | command grep "/$")) # remove packages extension COMPREPLY=(${COMPREPLY[@]%/}) # convert path syntax to package syntax cur="${COMPREPLY[*]//\//.}" fi } # 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 ;; esac done case $cur in # standard option completions -verbose:*) COMPREPLY=($(compgen -W 'class gc jni' -- "${cur#*:}")) return ;; -javaagent:*) cur=${cur#*:} _filedir '@(jar|zip)' return ;; -agentpath:*) cur=${cur#*:} _filedir so return ;; # various non-standard option completions -splash:*) cur=${cur#*:} _filedir '@(gif|jp?(e)g|png)' return ;; -Xbootclasspath*:*) _java_path return ;; -Xcheck:*) COMPREPLY=($(compgen -W 'jni' -- "${cur#*:}")) return ;; -Xgc:*) COMPREPLY=($(compgen -W 'singlecon gencon singlepar genpar' \ -- "${cur#*:}")) return ;; -Xgcprio:*) COMPREPLY=($(compgen -W 'throughput pausetime deterministic' \ -- "${cur#*:}")) return ;; -Xloggc:* | -Xverboselog:*) cur=${cur#*:} _filedir return ;; -Xshare:*) COMPREPLY=($(compgen -W 'auto off on' -- "${cur#*:}")) return ;; -Xverbose:*) COMPREPLY=($(compgen -W 'memory load jni cpuinfo codegen opt gcpause gcreport' -- "${cur#*:}")) return ;; -Xverify:*) COMPREPLY=($(compgen -W 'all none remote' -- "${cur#*:}")) return ;; # the rest that we have no completions for -D* | -*:*) return ;; esac case $prev in -cp | -classpath) _java_path return ;; 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 '[jw]ar' 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 ;; -doclet | -exclude | -subpackages | -source | -locale | -encoding | -windowtitle | \ -doctitle | -header | -footer | -top | -bottom | -group | -noqualifier | -tag | \ -charset | -sourcetab | -docencoding) return ;; -stylesheetfile) _filedir css return ;; -d | -link | -linkoffline) _filedir -d return ;; -classpath | -cp | -bootclasspath | -docletpath | -sourcepath | -extdirs | \ -excludedocfilessubdir) _java_path return ;; 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 ;; -cp | -classpath | -bootclasspath | -sourcepath | -extdirs) _java_path return ;; 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 | command 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: filetype=sh