# bash completion for java, javac and javadoc -*- shell-script -*- # available path elements completion _comp_cmd_java__classpath() { _comp_compgen -c "${cur##*:}" filedir '@(jar|zip)' } # exact classpath determination # @var[out] REPLY Array to store classpaths # @return 0 if at least one element is generated, or otherwise 1 _comp_cmd_java__find_classpath() { local i REPLY= # search first in current options for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == -@(cp|classpath) ]]; then REPLY=${words[i + 1]} break fi done # fall back to environment, followed by current directory _comp_split -F : REPLY "${REPLY:-${CLASSPATH:-.}}" } # exact sourcepath determination # @var[out] REPLY Array to store sourcepaths # @return 0 if at least one element is generated, or otherwise 1 _comp_cmd_java__find_sourcepath() { local i REPLY= # search first in current options for ((i = 1; i < cword; i++)); do if [[ ${words[i]} == -sourcepath ]]; then REPLY=${words[i + 1]} break fi done # fall back to classpath if [[ ! $REPLY ]]; then _comp_cmd_java__find_classpath return fi _comp_split -F : REPLY "$REPLY" } # available classes completion _comp_cmd_java__classes() { local REPLY i # find which classpath to use _comp_cmd_java__find_classpath local -a classpaths=("${REPLY[@]}") local -a classes=() # convert package syntax to path syntax local cur=${cur//.//} # parse each classpath element for classes for i in "${classpaths[@]}"; do if [[ $i == *.@(jar|zip) && -r $i ]]; then if type zipinfo &>/dev/null; then _comp_split -a classes "$(zipinfo -1 "$i" "$cur*" 2>/dev/null | command grep '^[^$]*\.class$')" elif type unzip &>/dev/null; then # Last column, between entries consisting entirely of dashes _comp_split -a classes "$(unzip -lq "$i" "$cur*" 2>/dev/null | _comp_awk '$NF ~ /^-+$/ { flag=!flag; next }; flag && $NF ~ /^[^$]*\.class/ { print $NF }')" elif type jar &>/dev/null; then _comp_split -a classes "$(jar tf "$i" "$cur" | command grep '^[^$]*\.class$')" fi elif [[ -d $i ]]; then local tmp _comp_compgen -v tmp -c "$i/$cur" -- -d -S . _comp_compgen -av tmp -c "$i/$cur" -- -f -X '!*.class' ((${#tmp[@]})) && _comp_compgen -av classes -- -X '*\$*' -W '"${tmp[@]#$i/}"' [[ ${classes-} == *.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 ((${#classes[@]} != 0)); then # remove class extension classes=("${classes[@]%.class}") # convert path syntax to package syntax classes=("${classes[@]//\//.}") _comp_compgen -U classes -- -W '"${classes[@]}"' fi } # available packages completion _comp_cmd_java__packages() { local REPLY i files # find which sourcepath to use _comp_cmd_java__find_sourcepath || return 0 local -a sourcepaths=("${REPLY[@]}") # convert package syntax to path syntax local cur=${cur//.//} # parse each sourcepath element for packages for i in "${sourcepaths[@]}"; do if [[ -d $i ]]; then _comp_expand_glob files '"$i/$cur"*' || continue _comp_split -la COMPREPLY "$( command ls -F -d "${files[@]}" 2>/dev/null | command sed -e 's|^'"$i"'/||' )" fi done if ((${#COMPREPLY[@]} != 0)); then # keep only packages with the package suffix `/` being removed _comp_split -l COMPREPLY "$(printf '%s\n' "${COMPREPLY[@]}" | command sed -n 's,/$,,p')" # convert path syntax to package syntax ((${#COMPREPLY[@]})) && COMPREPLY=("${COMPREPLY[@]//\//.}") fi } # java completion # _comp_cmd_java() { local cur prev words cword comp_args _comp_initialize -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 _comp_compgen_filedir return ;; esac done case $cur in # standard option completions -verbose:*) _comp_compgen -c "${cur#*:}" -- -W 'class gc jni' return ;; -javaagent:*) _comp_compgen -c "${cur#*:}" filedir '@(jar|zip)' return ;; -agentpath:*) _comp_compgen -c "${cur#*:}" filedir so return ;; # various non-standard option completions -splash:*) _comp_compgen -c "${cur#*:}" filedir '@(gif|jp?(e)g|png)' return ;; -Xbootclasspath*:*) _comp_cmd_java__classpath return ;; -Xcheck:*) _comp_compgen -c "${cur#*:}" -- -W 'jni' return ;; -Xgc:*) _comp_compgen -c "${cur#*:}" -- -W 'singlecon gencon singlepar genpar' return ;; -Xgcprio:*) _comp_compgen -c "${cur#*:}" -- -W 'throughput pausetime deterministic' return ;; -Xloggc:* | -Xverboselog:*) _comp_compgen -c "${cur#*:}" filedir return ;; -Xshare:*) _comp_compgen -c "${cur#*:}" -- -W 'auto off on' return ;; -Xverbose:*) _comp_compgen -c "${cur#*:}" -- -W 'memory load jni cpuinfo codegen opt gcpause gcreport' return ;; -Xverify:*) _comp_compgen -c "${cur#*:}" -- -W 'all none remote' return ;; # the rest that we have no completions for -D* | -*:*) return ;; esac case $prev in -cp | -classpath) _comp_cmd_java__classpath return ;; esac if [[ $cur == -* ]]; then _comp_compgen_help -- -help [[ $cur == -X* ]] && _comp_compgen -a help -- -X else if [[ $prev == -jar ]]; then # jar file completion _comp_compgen_filedir '[jw]ar' else # classes completion _comp_cmd_java__classes fi fi [[ ${COMPREPLY-} == -*[:=] ]] && compopt -o nospace _comp_ltrim_colon_completions "$cur" } && complete -F _comp_cmd_java java _comp_cmd_javadoc() { local cur prev words cword comp_args _comp_initialize -- "$@" || return case $prev in -overview | -helpfile) _comp_compgen_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) _comp_compgen_filedir css return ;; -d | -link | -linkoffline) _comp_compgen_filedir -d return ;; -classpath | -cp | -bootclasspath | -docletpath | -sourcepath | -extdirs | \ -excludedocfilessubdir) _comp_cmd_java__classpath return ;; esac # -linkoffline takes two arguments if [[ $cword -gt 2 && ${words[cword - 2]} == -linkoffline ]]; then _comp_compgen_filedir -d return fi if [[ $cur == -* ]]; then _comp_compgen_help -- -help else # source files completion _comp_compgen_filedir java # packages completion _comp_cmd_java__packages fi } && complete -F _comp_cmd_javadoc javadoc _comp_cmd_javac() { local cur prev words cword comp_args _comp_initialize -n : -- "$@" || return case $prev in -d) _comp_compgen_filedir -d return ;; -cp | -classpath | -bootclasspath | -sourcepath | -extdirs) _comp_cmd_java__classpath 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") _comp_compgen -c "${cur#*:}" -- -W "${opts//,/ }" return fi if [[ $cur == -* ]]; then _comp_compgen_help -- -help [[ $cur == -X* ]] && _comp_compgen -a help -- -X else # source files completion _comp_compgen_filedir java fi [[ ${COMPREPLY-} == -*[:=] ]] && compopt -o nospace _comp_ltrim_colon_completions "$cur" } && complete -F _comp_cmd_javac javac # ex: filetype=sh