아래는 내가 원하는 것입니다. 탭 완성이 모호한 경우 bash는 가능성 목록을 인쇄합니다. 목록의 각 단어에서 눌러야 할 다음 문자의 색상을 지정하고 싶습니다.
지금까지 내가 한 일은 다음과 같습니다. 내 .bashrc에서 다음 함수를 정의하고 전체 명령을 호출했습니다.
_colourunique() {
local word=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=($(compgen -f -- "${word}"))
if [[ "$word" ]] && [[ ${#COMPREPLY[@]} -gt 1 ]]; then
local w
local i=0
for ((i=0;i<${#COMPREPLY[@]};i++)) ; do
w=${COMPREPLY[$i]}
n=${#word}
COMPREPLY[$i]="${w:0:n}\033[91m${w:n:1}\033[0m${w:$((n+1))}"
done
fi
}
complete -D -F _colourunique
하지만 작동하지 않습니다... 입력할 때
ls D[TAB]
다음과 같이 자동으로 완료됩니다.
ls D\033[91m
문서, 데스크탑 등을 나열하는 가능성 대신 여기서 무엇이 잘못될 수 있나요? 아니면 이것을 달성하는 다른 간단한 방법이 있습니까?
업데이트 1:
나는 여기서 무슨 일이 일어나고 있는지 이해한다고 생각합니다. COMPREPLY의 모든 단어에 \033[91m을 추가했기 때문에 bash는 이 부분이 모든 사람에게 공통적이라고 생각하고 명령 프롬프트 자체에 해당 공통 용어를 자동 완성합니다. (단순히 목록을 인쇄하는 대신)
그래서 저는 COMPREPLY 배열을 편집하는 이런 방법이 올바른 방법이라고 생각하지 않습니다. 다른 방법이 있나요?
업데이트 2:
고유성을 유지하기 위해 문자열에 $i 및 \b를 추가해 보았습니다.
COMPREPLY[$i]="${w:0:n}$i\b\033[91m${w:n:1}\033[0m${w:$((n+1))}"
이제 아래와 같이 가능한 탭 완성이 인쇄됩니다.
D0\b\033[91mo\033[0mwnloads D1\b\033[91me\033[0msktop
이는 목록이 있는 그대로 인쇄된다는 의미입니다. \b 또는 \033[91m 문자는 평가되지 않았습니다. :-(
업데이트 3:
응답이 다음과 같으므로 bash에서 내가 원하는 것을 달성할 수 있는 방법이 없습니다(zsh로 이동하지 않는 한). 나는 대안을 받아들이기로 결정했습니다. 눈에 띄도록 다음 고유 키 입력을 각 단어 끝에 추가하려고 합니다.
아래는 지금까지의 코드입니다.
SanitiseString () {
local String="$1"
local j
for j in \\ \! \@ \# \$ \% \^ \& \* \( \) \+ \{ \[ \] \} \| \; \: \" \' \, \? \ ; do
String=${String//"$j"/\\"$j"}
done
echo "$String"
}
_colourunique() {
saveIFS=$IFS
IFS=$'\n'
local word=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=($(compgen -f -- "${word}"))
if [[ "$word" ]] ; then
local w
local i=0
for ((i=0;i<${#COMPREPLY[@]};i++)) ; do
w="${COMPREPLY[$i]}"
n=${#word}
w=$(SanitiseString "$w")
if [[ ${#COMPREPLY[@]} -gt 1 ]] ; then
COMPREPLY[$i]="$w :${w:n:1}"
else
COMPREPLY[$i]="$w"
fi
done
fi
IFS=$saveIFS
}
complete -D -F _colourunique
그러면 다음 고유 키 입력에 대한 옵션이 다음과 같이 구분되어 인쇄됩니다.
그러나 코드에는 여전히 두 가지 성가신 문제가 있습니다. 이 문제를 해결해야 해요
- 더 이상 자동 완성 디렉터리 끝에 /를 추가하지 않습니다.
- 자동 완성 후 스마트 간격이 더 이상 수행되지 않습니다.
어떤 제안이 있으십니까?
답변1
정확히 요청하신 내용은 아니지만, 처음에는 저와 같은 생각을 가지고 있었는데 결국 이렇게 해결했더니 색칠하는 것보다 낫다는 생각이 들어서 이 답변을 올리게 되었습니다.
이 옵션은 다음과 같이 설정할 수 있습니다.GNU 라인 읽기 라이브러리:
완성 접두사 표시 길이 수정 없이 표시되는 가능한 완성 목록의 공통 접두사의 문자 길이입니다. 0보다 큰 값으로 설정하면 가능한 완성을 표시할 때 해당 값보다 긴 공통 접두사가 줄임표로 대체됩니다.
예를 들어 이 줄~/.inputrc:
set completion-prefix-display-length 2
또한 성공합니다(공통 접두사가 2자보다 긴 경우).
답변2
내 .c는 그다지 뜨겁지는 않지만 내부에서 읽는 중입니다.http://git.savannah.gnu.org/cgit/bash.git/snapshot/bash-master.tar.gz, 제 생각에는 COMPREPLY는 비작동 텍스트 데이터에 지나지 않습니다. 아이오, 거기에 이스케이프 문자를 올바르게 가져오더라도 결국 우리가 표현하는 데 사용하는 문자의 비마법적/비특수 표현으로 인쇄될 것입니다.
단일 문자 "Escape"와 유사 \033
하거나 \e
대신 4~2개의 백슬래시 문자와 0, 3 및 Es가 있습니다.
printf
나는 .c를 살펴보기 전에 // echo
의 다양한 반복을 살펴 보며 실제로 어떻게 보이는지 확인했습니다.eval
처리됨COMPREPLY의 값입니다.
틀렸을 수도 있지만 체크인은 COMPREPLY가 STRINGLIST 유형의 구조인 것처럼 strlist_print()
보입니다 ( 에 정의됨 ).lib/sh/stringlist.c
externs.h