简体   繁体   中英

How can I make bash auto-complete java qualified class names when executing a main class

It's tedious to manually type in a class name for a java main class, especially in a deep package structure. I would like bash tab-completion to autocomplete class names based on the directory structure of the class.

How can I customize bash to do this?

(I have added my own solution but I will accept a better answer.)

The bash builtin command complete can be used to customize tab-completion in bash.

See bash documentation for more info.

Briefly, this can be done by specifying a custom completion function for java, complete -F _comp_java java . The function can then use the variables COMP_WORDS and COMP_CWORD to access the words (and current word index) in a command line to generate a list of possible completions. The possible completions must be placed in the array COMPREPLY. The compgen builtin can be combined with the output of the ls command to find all paths that begin with the current word. These possible completions can then be modified to replace slashes with dots.

Here is one way to do this. Any cleaner solutions will be accepted.

_comp_java () {
    prev=${COMP_WORDS[$COMP_CWORD - 1]}

    case $prev in
        "-jar")
            COMPREPLY=($(compgen -A file -- ${COMP_WORDS[$COMP_CWORD]}))
            ;;
        *)
            fields=($(echo ${COMP_WORDS[$COMP_CWORD]} | tr "." "\n"));
            [ "${COMP_WORDS[$COMP_CWORD]: -1}" == "." ] && lastIdx=0 || lastIdx=1
            [ ${#COMP_WORDS[$COMP_CWORD]} -eq 0 ] || [ ${lastIdx} -eq 0 ] && lastWord='' || lastWord=${fields[${#fields[@]}-1]}
            [ ${#COMP_WORDS[$COMP_CWORD]} -eq 0 ] && fields=() || fields=($(echo ${fields[*]:0:${#fields[@]}-$lastIdx}))
            [ ${lastIdx} -eq 0 ] && prefix=${COMP_WORDS[$COMP_CWORD]} || prefix=$(tr ' ' '.' <<< $(echo "${fields[@]}."))
            [ "${prefix:0}" == "." ] && prefix=""

            COMPREPLY=( $(compgen -W "$(ls $(tr ' ' '/' <<< $(echo ${fields[@]})))" -- $lastWord ))
            COMPREPLY=(${COMPREPLY[@]/#/$prefix})
            COMPREPLY=(${COMPREPLY[@]/%/.})
            COMPREPLY=(${COMPREPLY[@]/.class./})
            COMPREPLY=(${COMPREPLY[@]/.java./})
            ;;
    esac
    return 0
}

complete -o nospace -o filenames -F _comp_java java

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM