기존 도구에 bash 완성 기능을 추가하고 있습니다.
누군가 -s
플래그를 전달한 후 bash 완료와 관련된 몇 가지 옵션을 제공하고 싶습니다.
Closed
Feedback
"In Progress"
New
Rejected
Resolved
내부 공간이 "In Progress"
문제를 일으켰습니다.
#!/usr/bin/env bash
_remote-redmine()
{
local cur
COMPREPLY=()
cur=${COMP_WORDS[$COMP_CWORD]}
case "${COMP_WORDS[($COMP_CWORD-1)]}" in
-s)
s_opts=( "New" "In Progress" "Resolved" "Feedback" "Closed" "Rejected" )
COMPREPLY=( $( compgen -W "${s_opts[*]}" -- "$cur") )
;;
esac
return 0
}
complete -F _remote-redmine remote-redmine
도구를 실행하면 다음과 같은 결과를 얻습니다.
$ remote-redmine -s <tab><tab>
Closed Feedback In New Progress Rejected Resolved
하지만 나는 다음을 얻고 싶다:
$ remote-redmine -s <tab><tab>
Closed Feedback "In Progress" New Rejected Resolved
또는
$ remote-redmine -s <tab><tab>
Closed Feedback In\ Progress New Rejected Resolved
내가 시도한 것들:
s_opts=( ... "In\ Progress" ... )
: 차이 없음s_opts( ... "In\\ Progress" ...)
: 차이 없음s_opts( ... "In\\\ Progress" ...)
: 두 가지 옵션은In\
다음과 같습니다.Progress
s_opts( ... "\"In Progress\"" ...)
: 차이 없음compgen -o nospace ...
: 차이 없음compgen -o noquote ...
: 차이 없음최소한 한 줄을
compgen
넣을 수는 있지만In Progress
다음과 같이 번역되지는 않습니다.complete
$ compgen -W 'New "In Progress"' New In Progress
추가 따옴표를 이스케이프하면 도움이 되지만
compgen
다음과 같이 변환되지는 않습니다complete
.$ compgen -W 'New "\"In Progress\""' New "In Progress"
공백을 세 번 이스케이프 처리하면 도움이 되지만 여전히 다음과 같이 변환되지는 않습니다
complete
.$ compgen -W 'New In\\\ Progress' New In\ Progress
나는 공간을 일곱 번 탈출하는 것이
complete
이러한 문제 중 일부를 해결할 수 있기 때문에 유망하다고 생각했지만 그것도 도움이 되지 않습니다.$ compgen -W 'New In\\\\\\\ Progress' New In\\\ Progress ... $ remote-redmine -s <tab><tab> ... In\\\ New Progress ...
우회는
compgen
작동하지만 단일 탭의 자동 채우기 및 이중 탭의 필터링이 손실됩니다.COMPREPLY=( ... 'In\ Progress' ... ) COMPREPLY=( ,,, '"In Progress"' ... )
답변1
이는 토큰화 및 IFS의 기본값과 관련이 있는데 이는 놀라운 일이 아닙니다.
존재하다
compgen -W "${s_opts[*]}"
배열 확장은 첫 번째 문자를 구분 기호로 사용하여 [*]
배열 요소를 단일 문자열로 연결합니다. IFS
기본적으로 공백이므로 값의 공백과 구분 기호로서의 공백 간의 구분이 손실됩니다. 다행히 compgen -W
인수는 문자로 구분된 값의 문자열로 해석되므로 비슷한 값이나 값에 나타나지 않는 다른 값으로만 변경하면 IFS
잘 작동합니다.[*]
IFS
:
그런 다음
COMPREPLY=( $( compgen ...) )
compgen
print를 사용하여 문자열을 암시적으로 분할하고 IFS
(와일드카드를 통해 전달), compgen
특히 줄바꿈으로 구분된 값을 인쇄하는 것 같습니다. 분할하여 이 작업을 수행하려면 줄 바꿈을 설정해야 IFS
하지만 readarray
어쨌든 줄 바꿈을 사용하고 와일드카드를 사용하지 않기 때문에 실제로 읽는 데 사용하는 것이 더 좋습니다.
그래서, 당신은 이것을 할 수 있습니다
_remote-redmine() {
local cur
local IFS=:
COMPREPLY=()
cur=${COMP_WORDS[$COMP_CWORD]}
case "${COMP_WORDS[($COMP_CWORD-1)]}" in
-s)
s_opts=( "New" "In Progress" "Resolves" "Feedback" "Closed" "Rejected" )
readarray -t COMPREPLY < <( printf "%q\n" $(compgen -W "${s_opts[*]}" -- "$cur"))
;;
esac
return 0
}
또는 줄 바꿈이 두 위치 모두에서 유효하므로 IFS=$'\n'
이전과 같이 출력을 설정하고 분할할 수 있지만 함수 기간 동안 와일드카드를 비활성화해야 합니다. 이는 저장하고 복원할 또 다른 전역 상태입니다.
답변2
이것은 나에게 효과적입니다. 사용하는 compgen
대신 $cur
:
_remote-redmine()
{
local cur
local item
COMPREPLY=()
cur=${COMP_WORDS[$COMP_CWORD]}
case "${COMP_WORDS[($COMP_CWORD-1)]}" in
-s)
local s_opts=( "New" "In\ Progress" "Resolved" "Feedback" "Closed" "Rejected" )
for item in "${s_opts[@]}"; do
case "$item" in
( "$cur"* )
COMPREPLY+=( "$item" )
;;
esac
done
;;
esac
return 0
}
complete -F _remote-redmine remote-redmine
내가 추가한 백슬래시에 주목하세요: "In\ Progress"
. 이것은 말 그대로 프로젝트의 일부입니다. 을 입력 In
하고 클릭 하면 명령줄이 입력됩니다. 이제 이스케이프 문자가 큰따옴표 외부에 있으므로 활성화됩니다. 즉, 단어 분할을 방지합니다 Tab.In\ Progress