bash의 내장 명령어인 complete
는 지정된 명령어에 대해 자동완성을 제공해준다. (tab키로 사용가능)
-p <name>: <name> 명령어에 등록된 자동완성 목록을 보여준다. (<name> 생략시 모든 목록 출력)
-r <name>: <name>에 설정된 자동완성을 제거한다.
-W <wordlist> <name>: <name>에 설정할 <wordlist>(단어 목록)을 지정한다.
-F <function> <name>: <name>에 설정할 <functon>(함수)을 지정한다.
-W <wordlist>
를 통해 test(임시 명령어)에 --help, --horizon, --version
에 대한 자동완성을 지원하도록 설정하였다.
<wordlist>
를 정의할 때 단어들은 $IFS
값에 따라 분리되며, 기본값은 <space><tab><newline>
으로 되어있다.
만약 <wordlist>
를 multiple words로 구성하고 싶다면, IFS 값을 아래와 같이 설정하면 된다.
_foo() {
local IFS=$'\n'
local words="
--help: 도움말
--version: 현재 foo의 버전을 나타냄
--test: 기본값으로 foo를 호출함
"
COMPREPLY=($(compgen -W "$words" -- "$2"))
}
complete -F _foo foo
# .bashrc
_foo() {
COMPREPLY=($(compgen -W "--help --version --horizon" -- "$2"))
}
complete -F _foo foo
자동완성 함수를 지정하기 위해서 사용되며, 자동완성 함수는 일반 함수와 같고 정의될 때 alias가 확장된다.
기본적으로 $1
, $2
, $3
가 지정되고 의미는 아래와 같다.
foo --version --help --horizon
\ | \
\_ $1 |_$3 \_$2
(command) (previous) (current)
현재까지 입력한 명령 라인의 인수들을 값으로 가지고 있는 array 변수이다.
위의 예시에서는 COMP_WORDS[0]=foo
, COMP_WORDS[1]=--version
, COMP_WORDS[2]=--help
, COMP_WORDS[3]=--horizon
가 된다. (c언어의 argv랑 같다고 보면 된다)
현재 커서가 위치한 인수의 index를 나타내며, 위에서 적은 예시에서는 3이 된다.
$2 == ${COMP_WORDS[COMP_CWORD]}
$3 == ${COMP_WORDS[COMP_CWORD - 1]}
이 값들($1, $2, $COMP_CWORD
)은 커서의 현재 위치에 따라 달라진다.
현재 프롬프트 상에서 작성 중인 명령 라인 전체를 나타낸다.
명령 라인에서 현재 커서가 위치한 문자수 index를 나타낸다.
tab 키를 눌렀을 때 보여지는 내용을 담는 array 변수이다. 값이 출력될 때는 자동으로 중복이 제거되고 sort되어 출력된다.
$ test --[teb][tab]
--help: 도움말
--version: 현재 foo의 버전을 나타냄
--test: 기본값으로 foo를 호출함
$ test --
자동완성을 위와 같이 줄바꿈해서 출력하고 싶다면, bind "set completion-display-width 0"
명령을 이용하면 된다.
모든 명령어에 자동완성 목록이 줄바꿈이 되는 것을 원한다면 ~/.inputrc
에 아래와 같이 적어주면 된다.
# ~/.inputrc
set completion-display-width 0
특정 명령어에서만 적용하고 줄바꿈을 적용하고 싶다면, 아래와 같이 해주면 된다.
_test() {
local IFS=$'\n'
local words="
--help: 도움말
--version: 현재 foo의 버전을 나타냄
--test: 기본값으로 foo를 호출함
"
# 이 명령어에만 줄바꿈을 설정하고, 원래대로 되돌리기 위해서 현재 설정된 width를 가져옴
local width=$(bind -v | sed -n 's/^set completion-display-width //p')
if [[ $width -ne 0 ]]; then
# 자동완성 줄바꿈 설정
bind "set completion-display-width 0"
# width 값을 이전 값으로 되돌림
PROMPT_COMMAND="bind 'set completion-display-width $width'"
fi
COMPREPLY=($(compgen -W "${words}" -- "$2"))
}
complete -F _test test
_git() {
local width=$(bind -v | sed -n 's/^set completion-display-width //p')
if [[ $width -ne 0 ]]; then
bind "set completion-display-width 0"
PROMPT_COMMAND="bind 'set completion-display-width $width'"
fi
local IFS=$'\n'
local options="
push: main branch의 커밋을 원격 저장소로 올리기
reset: HEAD의 포인터를 특정 위치로 옮김
"
local pushs="
-f: 원격 저장소의 내용을 강제로 현재 branch의 내용으로 덮어씀
-u: upstream 브랜치 연결 설정
"
local resets="
--hard: 돌아간 커밋 이후의 변경 이력을 모두 삭제
--soft: 변경 이력은 모두 삭제하지만, 변경 내용은 유지되며 stage에 남음
"
if (( COMP_CWORD == 1 )); then
COMPREPLY=( $(compgen -W "$options" -- "$2") )
return
fi
if (( COMP_CWORD == 2 )); then
case $3 in
reset)
COMPREPLY=($(compgen -W "$resets" -- "$2"))
return ;;
push)
COMPREPLY=($(compgen -W "$pushs" -- "$2"))
return;;
esac
fi
}
complete -F _git git