# bash completion for java, javac and javadoc -*- shell-script -*- # available path elements completion proc _java_path { setglobal cur = $(cur##*:) _filedir '@(jar|zip)' } # exact classpath determination proc _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 ]] && setglobal classpath = $CLASSPATH # default to current directory [[ -z $classpath ]] && setglobal classpath = '.' } # exact sourcepath determination proc _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 ]] { local classpath _java_find_classpath setglobal sourcepath = $classpath } } # available classes completion proc _java_classes { local classpath i # find which classpath to use _java_find_classpath # convert package syntax to path syntax setglobal cur = $(cur//.//) # parse each classpath element for classes for i in [$(classpath//:/ )] { if [[ "$i" == *.@(jar|zip) && -r $i ]] { if type zipinfo &>/dev/null { setglobal COMPREPLY = ''( $( zipinfo -1 "$i" "$cur*" 2>/dev/null | \ command grep '^[^$]*\.class$' ) ) } else { setglobal COMPREPLY = ''( $( jar tf "$i" "$cur" | \ command grep '^[^$]*\.class$' ) ) } } elif [[ -d $i ]] { setglobal 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? } } # remove class extension setglobal COMPREPLY = ''( ${COMPREPLY[@]%.class} ) # convert path syntax to package syntax setglobal COMPREPLY = ''( ${COMPREPLY[@]//\//.} ) } # available packages completion proc _java_packages { local sourcepath i # find which sourcepath to use _java_find_sourcepath # convert package syntax to path syntax setglobal cur = $(cur//.//) # parse each sourcepath element for packages for i in [$(sourcepath//:/ )] { if [[ -d $i ]] { setglobal COMPREPLY = ''( $( command ls -F -d $i/$cur* 2>/dev/null | \ sed -e 's|^'$i'/||' ) ) } } # keep only packages setglobal COMPREPLY = ''( $( tr " " "\n" <<<"${COMPREPLY[@]}" | command grep "/$" ) ) # remove packages extension setglobal COMPREPLY = ''( ${COMPREPLY[@]%/} ) # convert path syntax to package syntax setglobal cur = $(COMPREPLY[@]//\//.) } # java completion # proc _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 match $cur { # standard option completions with -verbose:* setglobal COMPREPLY = ''( $( compgen -W 'class gc jni' -- "${cur#*:}" ) ) return 0 with -javaagent:* setglobal cur = $(cur#*:) _filedir '@(jar|zip)' return 0 with -agentpath:* setglobal cur = $(cur#*:) _filedir so return 0 # various non-standard option completions with -splash:* setglobal cur = $(cur#*:) _filedir '@(gif|jp?(e)g|png)' return 0 with -Xbootclasspath*:* _java_path return 0 with -Xcheck:* setglobal COMPREPLY = ''( $( compgen -W 'jni' -- "${cur#*:}" ) ) return 0 with -Xgc:* setglobal COMPREPLY = ''( $( compgen -W 'singlecon gencon singlepar genpar' \ -- "${cur#*:}" ) ) return 0 with -Xgcprio:* setglobal COMPREPLY = ''( $( compgen -W 'throughput pausetime deterministic' \ -- "${cur#*:}" ) ) return 0 with -Xloggc:*|-Xverboselog:* setglobal cur = $(cur#*:) _filedir return 0 with -Xshare:* setglobal COMPREPLY = ''( $( compgen -W 'auto off on' -- "${cur#*:}" ) ) return 0 with -Xverbose:* setglobal COMPREPLY = ''( $( compgen -W 'memory load jni cpuinfo codegen opt gcpause gcreport' -- "${cur#*:}" ) ) return 0 with -Xverify:* setglobal COMPREPLY = ''( $( compgen -W 'all none remote' -- "${cur#*:}" ) ) return 0 # the rest that we have no completions for with -D*|-*:* return 0 } match $prev { with -cp|-classpath _java_path return 0 } if [[ "$cur" == -* ]] { setglobal COMPREPLY = ''( $( compgen -W '$( _parse_help "$1" -help )' -- "$cur" ) ) [[ $cur == -X* ]] && \ setglobal COMPREPLY = ''( $( compgen -W '$( _parse_help "$1" -X )' -- "$cur" ) ) } else { if [[ "$prev" == -jar ]] { # jar file completion _filedir jar } else { # classes completion _java_classes } } [[ $COMPREPLY == -*[:=] ]] && compopt -o nospace __ltrim_colon_completions $cur } && complete -F _java java proc _javadoc { local cur prev words cword _init_completion || return match $prev { with -overview|-helpfile _filedir '?(x)htm?(l)' return 0 with -stylesheetfile _filedir css return 0 with -d|-link|-linkoffline _filedir -d return 0 with -classpath|-bootclasspath|-docletpath|-sourcepath|-extdirs _java_path return 0 } # -linkoffline takes two arguments if [[ $cword -gt 2 && ${words[$cword-2]} == -linkoffline ]] { _filedir -d return } if [[ "$cur" == -* ]] { setglobal COMPREPLY = ''( $( compgen -W '$( _parse_help "$1" -help )' -- "$cur" ) ) } else { # source files completion _filedir java # packages completion _java_packages } } && complete -F _javadoc javadoc proc _javac { local cur prev words cword _init_completion -n : || return match $prev { with -d _filedir -d return 0 with -classpath|-bootclasspath|-sourcepath|-extdirs _java_path return 0 } if [[ $cur == -+([a-zA-z0-9-_]):* ]] { # Parse required options from -foo:{bar,quux,baz} local helpopt=-help [[ $cur == -X* ]] && setglobal 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] setglobal COMPREPLY = ''( $( compgen -W "${opts//,/ }" -- "${cur#*:}" ) ) return } if [[ "$cur" == -* ]] { setglobal COMPREPLY = ''( $( compgen -W '$( _parse_help "$1" -help )' -- "$cur" ) ) [[ $cur == -X* ]] && \ setglobal COMPREPLY = ''( $( compgen -W '$( _parse_help "$1" -X )' -- "$cur" ) ) } else { # source files completion _filedir java } [[ $COMPREPLY == -*[:=] ]] && compopt -o nospace __ltrim_colon_completions $cur } && complete -F _javac javac # ex: ts=4 sw=4 et filetype=sh