简体   繁体   中英

How to make two programs to use only one auto-completion function in bash?

I followed this tutorial to setup auto-completion functions for figlet / toilet .

# bash completion for figlet/toilet

have figlet &&
_figlet()
{
    local prev cur opts
    _get_comp_words_by_ref cur prev
    opts="-f"

    COMPREPLY=()

    case $prev in
        -f)
            local running=$(find /usr/share/figlet -name '*.flf' -printf '%P\n' | sed 's/\.flf$//')
            COMPREPLY=( $(compgen -W "${running}" -- ${cur}) )
            return 0
            ;;
        *)
            ;;
    esac

    COMPREPLY=( $( compgen -W "$opts" -- "$cur" ) )

    return 0
} &&
complete -F _figlet figlet

###################################################################################################

have toilet &&
_toilet()
{
    local prev cur opts
    _get_comp_words_by_ref cur prev
    opts="-f"

    COMPREPLY=()

    case $prev in
        -f)
            local running=$(find /usr/share/figlet -name '*.[tf]lf' -printf '%P\n' | sed 's/\.[tf]lf$//')
            COMPREPLY=( $(compgen -W "${running}" -- ${cur}) )
            return 0
            ;;
        *)
            ;;
    esac

    COMPREPLY=( $( compgen -W "$opts" -- "$cur" ) )

    return 0
} &&
complete -F _toilet toilet

_figlet and _toilet are almost identical except the pattern in find / sed commands.
How to extract a function called _figlet_toilet which takes a pattern as argument?

From: http://www.gnu.org/software/bash/manual/html_node/Programmable-Completion.html

After these matches have been generated, any shell function or command specified with the -F and -C options is invoked. When the command or function is invoked, the COMP_LINE, COMP_POINT, COMP_KEY, and COMP_TYPE variables are assigned values as described above (see Bash Variables). If a shell function is being invoked, the COMP_WORDS and COMP_CWORD variables are also set. When the function or command is invoked, the first argument is the name of the command whose arguments are being completed , the second argument is the word being completed, and the third argument is the word preceding the word being completed on the current command line. No filtering of the generated completions against the word being completed is performed; the function or command has complete freedom in generating the matches.


# bash completion for figlet/toilet

{
    have figlet || have toilet
} &&
_figlet_toilet()
{
    local prev cur opts pat
    _get_comp_words_by_ref cur prev
    opts="-f"

    COMPREPLY=()

    case $prev in
        -f)
            case "${1}" in
                figlet)
                    pat='flf'
                ;;
                toilet)
                    pat='[tf]lf'
                ;;
            esac
            local running=$(find /usr/share/figlet -name "*.${pat}" -printf '%P\n' | sed "s/\.${pat}\$//")
            COMPREPLY=( $(compgen -W "${running}" -- ${cur}) )
            return 0
            ;;
        *)
            ;;
    esac

    # if '-f' is already given, then generate random string
    for (( i=0; i < ${#COMP_WORDS[@]}-1; i++ )); do
        if [[ ${COMP_WORDS[i]} == -f ]]; then
            # COMPREPLY=("'$(fortune -sn42)'")
            return 0
        fi
    done

    COMPREPLY=( $( compgen -W "$opts" -- "$cur" ) )

    return 0
} &&
complete -F _figlet_toilet figlet toilet

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