Bash의 내장 명령(Built-in Command)중 하나인 complete는 특정 명령에 대한 자동완성(Autocomplete) 목록을 정의한다.
자동완성 정의 명령 - complete
자동완성 추천 단어 목록(Suggestions)이 고정되어 있으면 ~/.bashrc에 complete명령 한 줄만 추가해서 커스텀 자동완성을 정의할 수 있긴 하다. 하지만, 대개 추천 목록을 그때 그때 상황에 맞춰 동적으로 생성해야 하는 경우가 대부분이므로, 다음과 같이 -F 옵션으로 자동완성 함수를 지정하는 방식으로 사용한다.
complete -F <함수> <명령>
셸에 <명령>을 입력하고 [Tab]키를 눌러서 자동완성을 시도하면 <함수>가 호출된다. <함수>가 추천 단어 목록을 만들어 반환하면 자동완성이 되거나(추천 단어가 1개인 경우), 셸에 추천 단어들이 출력(추천 단어가 여러개인 경우)된다.
자동완성 스크립트
커스텀 자동완성을 정의할 때는 (편의상) 명령별로 스크립트를 따로 만들어 /etc/bash_completion.d/ 디렉토리에 집어넣어 사용한다. 이 디렉토리 내의 자동완성 스크립트들은 로그인 시점에 실행되어 사용자 셸에 적용된다. (특정 사용자에게만 사용 가능한 자동완성을 정의하려면 ~/.bashrc를 활용하면 된다.)
다음은 mycmd 명령에 대해 /var/www/의 하위 디렉토리들에 대한 경로를 자동완성으로 제공하는 스크립트의 예시이다.
_mycmd_autocomplete() { local cur cur=${COMP_WORDS[COMP_CWORD]} COMPREPLY=( $(compgen -W '$(find /var/www -mindepth 1 -maxdepth 1 -type d -printf "%P ")' -- $cur ) ) } complete -F _mycmd_autocomplete mycmd
자동완성 함수는 전역변수 COMPREPLY를 통해 자동완성 추천 단어 목록을 전달한다. 이 때, 목록에서 현재 입력중인 단어를 Prefix로 하는 단어들만 추려내기 위해 compgen 명령을 보조로 사용한다.
compgen -W '단어1 단어2 ... 단어N' -- "<Prefix>"
뒤쪽의 "-- $cur" 부분이 현재 입력중인 단어를 전달하는 인수이다. 이 $cur를 만들어내기 위해 다음 전역 변수들을 사용하였다. 이 전역 변수들은 자동완성 함수가 호출될 때 세팅되어 전달된다.
- $COMP_WORDS: 현재 셸에 입력된 단어(공백으로 구분된 토큰) 목록
- $COMP_CWORD: 현재 셸에 입력중인 단어의 순번(Index)
예를 들어, 셸에 다음과 같이 입력하고 자동완성을 위해 [Tab]키를 눌렀을 때, 자동완성 함수에 전달되는 전역변수들은 다음과 같이 세팅된다.
mycmd /var/www/andromeda /var/www/t
$COMP_WORDS[0] = "mycmd" $COMP_WORDS[1] = "/var/www/andromeda" $COMP_WORDS[2] = "/var/www/t" $COMP_CWORD = 2
참고: $COMP_CWORD가 항상 $COMP_WORDS의 Index 최대값과 같지는 않은데, 입력 중인 명령의 중간 부분에서 자동완성을 시도할 수도 있기 때문이다.
자동완성 스크립트 응용
자동완성 함수 호출시 함께 전달되는 전역변수들을 잘 활용하면 추천 목록을 보다 세밀하게 다듬어서 제공할 수 있다.
아래 자동완성 스크립트는 위의 예시를 조금 변형해서 다음과 같은 기능을 추가한 것이다.
- 첫 번째 인수에 대해서만 자동완성을 실행한다.
- 전체 경로가 아닌, 디렉토리 이름만을 자동완성으로 제공한다.
_mycmd_autocomplete() { local cur list cur=${COMP_WORDS[COMP_CWORD]} list="" if [ ${COMP_CWORD} != 1 ]; then return fi for dir in $(find /var/www/ -mindepth 1 -maxdepth 1 -type d); do list="${list} $(basename ${dir})" done COMPREPLY=( $(compgen -W '${list}' -- $cur ) ) } complete -F _mycmd_autocomplete mycmd