-
Bash와 Zsh에서 이미 완성된 단어에도 설명을 표시하는 탭 자동완성 기능을 구현하는 방법 소개
- Bash와 Zsh는 서로 다른 탭 자동완성 API를 사용하며, Zsh만 기본적으로 자동 완성에 설명 보이기 기능을 제공함
-
_generate_foo_completions로 후보를 생성하고, Bash에서는 COMPREPLY, Zsh에서는 compadd로 반환하는 구조를 구현함
- Zsh의 설명 기능을 Bash에도 구현하기 위해 후보 문자열에 설명을 포함하고, 단일 후보일 때만 설명을 제거하는 방식으로 처리함
- 단일 후보일 경우에도 의도적으로 모호성을 추가해 <TAB> 입력 시 설명이 표시되도록 개선함
- 최종 스크립트는 두 쉘에서 동일한 사용자 경험을 제공하며, 부분 완성·전체 완성·후보 설명 표시 모두 지원함
문제 배경
-
탭 자동완성(tab-completion) 은 명령어나 플래그를 탐색할 때 유용하며, 특히 API나 CLI 도구를 처음 접할 때 도움을 줌
- Zsh는 기본적으로 여러 후보가 있을 때만 설명을 표시하고, Bash는 별도 설정을 통해서만 가능함
- 하지만 이미 완성된 단어에 대해서는 두 셸 모두 설명을 표시하지 않음
- 이로 인해 사용자가 설명을 보려면 다음과 같은 번거로운 과정을 거쳐야 함
- 일부 문자를 삭제하여 여러 후보가 매칭되도록 함
-
<TAB> 키를 눌러 후보 목록을 확인
- 원하는 설명을 시각적으로 찾음
- 삭제한 문자를 다시 입력하여 명령 실행
해결 방법 개요
- 단일 후보일 경우에도 더미 후보(dummy completion) 를 추가하여 후보를 모호하게 만듦
- 이렇게 하면 Bash와 Zsh 모두 후보 목록과 함께 설명을 출력하게 됨
- 단, 실제 명령어에 설명 텍스트가 삽입되지 않도록 주의해야 함
기본 개념
- 탭 자동완성은 <TAB> 입력 시 현재 단어와 커서 위치를 받아, 가능한 후보 목록을 반환하는 방식으로 동작함
- Bash: COMPREPLY 배열에 후보를 할당
- Zsh: compadd 명령으로 후보를 등록
-
_generate_foo_completions 함수는 후보 문자열을 출력하며, 실전에서는 CLI의 상태를 기반으로 동적 생성 가능
Bash와 Zsh 동시 지원하기
-
_complete_foo_bash와 _complete_foo_zsh 함수로 각각의 쉘에 맞게 구현
-
if [ -n "${ZSH_VERSION:-}" ]; then ... elif [ -n "${BASH_VERSION:-}" ]; then ... fi로 구분
- 사용자는 스크립트를 .bashrc나 .zshrc에 등록 후 적용
Zsh에서의 설명 표시
- 후보 문자열에 이름: 설명 형식 사용
- Zsh: compadd -d raw -- $trimmed로 이름과 설명을 병렬 배열로 전달
- Bash: 설명 부분을 제거한 후보만 COMPREPLY에 전달 (기본적으로 설명 미지원)
Bash에서 설명 구현하기
- 여러 후보일 경우 설명이 포함된 문자열을 그대로 노출
- 단일 후보일 경우에만 설명 제거
- Bash의 자동완성이 공통 접두어만 삽입하는 동작을 이용해 설명이 실제 입력에는 포함되지 않도록 함
단일 후보에서도 설명 표시
- 완성된 단어에 <TAB> 입력 시에도 설명을 보여주기 위해 더미 후보를 추가해 모호성을 유도
- Zsh: 두 개의 병렬 배열(raw, trimmed) 모두에 더미 후보 추가
- Bash: 단일 후보일 경우 trimmed에 이름만 추가
최종 결과
- 다중 후보 시 이름+설명 모두 표시
- 단일 후보 시에도 <TAB>로 설명 확인 가능
- Bash와 Zsh 모두 동일한 경험 제공
- 적용 예:
$ foo <TAB>
apple: a common fruit banana: starchy and high in potassium
apricot: sour fruit... cherry: small and sweet...