bash-completion: 공백이 포함된 인용 제안 추가

bash-completion: 공백이 포함된 인용 제안 추가

기존 도구에 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 ...) )

compgenprint를 사용하여 문자열을 암시적으로 분할하고 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

관련 정보