가능한 완료를 어떻게 반복합니까? [복사]

가능한 완료를 어떻게 반복합니까? [복사]

주어진 부분 명령에 대해 가능한 완료 범위를 얻을 수 있기를 원합니다. 예를 들어 일부 명령에는 service um다음과 같은 완성이 가능합니다.

$ service um<TAB><TAB>
umountfs      umountnfs.sh  umountroot

completions다음 동작을 가진 함수를 원합니다 .

$ for x in $(completions 'service um'); do
> echo $x
> done
umountfs
umountnfs.sh
umountroot

진행 상황의 일부: 지금까지 배운 내용

나는 이것이 완전한 대답이 될 수 있는 하나의 접근법이라고 생각합니다. 나는 확실히 완전한 답변을 보고 싶지만 <TAB><TAB>프로그래밍 방식이 아닌 방식으로 동일한 기능을 제공하는 상대적으로 간단한 접근 방식을 고려할 때 더 유연한 솔루션이 있을 수 있을 것 같습니다.

service이 명령의 완료 메커니즘은 _service다음 함수 라는 것을 알 수 있습니다 .

$ complete -p service
complete -F _service service

이 완성 함수가 호출되면 _service여러 환경 변수가 설정됩니다(예 COMP_{LINE,POINT,KEY,TYPE,WORDS,CWORD}: ; 참조).배쉬 매뉴얼 페이지), 이 함수는 완성되는 명령, 완성되는 단어 및 이전 단어를 인수로 취하고 COMPREPLY가능한 완성을 채웁니다. 따라서 내가 원하는 기능은 completions다음과 같이 정의할 수 있습니다.

function completions() {
    # Produce an array of tokens in the input.
    read -a words <<< $1

    # Use "complete -p ${words[0]}" to determine how the 
    # completions are computed. This could be complicated
    # if complete is given flags other than -F.
    completion_func=???

    # Set all those COMP_* environment variables appropriately.

    # Run the function to populate COMPREPLY. This version
    # assumes words has length at least 2, but that can be
    # fixed.
    $completion_func ${words[0]} ${words[-1]} ${words[-2]}

    echo ${COMPREPLY[@]}
}

상대적인 복잡성 외에도 <TAB><TAB>이 접근 방식의 단점은 환경을 변경한다는 것입니다.

답변1

여기에 출발점으로 사용할 수 있다고 생각되는 기본 기능이 있습니다. 여러 가지 방법으로 실패할 수 있습니다. 여기 다른 누군가가 이를 개선할 수 있기를 바랍니다.

completions () (
    if [ -f /usr/share/bash-completion/bash_completion ]; then
        . /usr/share/bash-completion/bash_completion
    elif [ -f /etc/bash_completion ]; then
        . /etc/bash_completion
    fi

    IFS="$COMP_WORDBREAKS" read -a words <<<"$1"
    complete_setting=($(complete -p "${words[0]}"))
    complete_optstring=":abcdefgjksuvprDEo:A:G:W:F:C:X:P:S:"
    while getopts "$complete_optstring" option "${complete_setting[@]:1}"
    do
        case $option in
            F) complete_functon="$OPTARG"
                ;;
            *) # Run around screaming!                    
                ;;
        esac
    done
    COMP_WORDS=("${words[@]}")
    COMP_LINE="$1"
    COMP_POINT="${#COMP_LINE}"
    COMP_CWORD=$((${#COMP_WORDS[@]} - 1))
    "$complete_functon" 
    printf "%s\n" "${COMPREPLY[@]}"
)

노트:

  • 대화형 셸에서 함수로 사용하는 경우 초기 소스가 필요하지 않습니다.
  • complete찾기 단어 Split 을 사용하므로 for 로 설정 COMP_WORDBREAKS했습니다 .IFSread
  • complete -p재사용 가능한 방식으로 현재 완성 설정을 인쇄하면 원래 방식대로 옵션을 구문 분석할 수 있습니다.
  • ()이 함수는 ( 대신 ) 서브쉘을 사용하므로 {}현재 환경이 방해받지 않아야 합니다.

관련 정보