주어진 부분 명령에 대해 가능한 완료 범위를 얻을 수 있기를 원합니다. 예를 들어 일부 명령에는 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
했습니다 .IFS
read
complete -p
재사용 가능한 방식으로 현재 완성 설정을 인쇄하면 원래 방식대로 옵션을 구문 분석할 수 있습니다.()
이 함수는 ( 대신 ) 서브쉘을 사용하므로{}
현재 환경이 방해받지 않아야 합니다.