Bash의 전체 또는 compgen -C(명령) 옵션을 사용하는 방법은 무엇입니까?

Bash의 전체 또는 compgen -C(명령) 옵션을 사용하는 방법은 무엇입니까?

이 옵션은 bash에서 쉘 완성을 생성할 때 -C매우 강력하고 일반적으로 보입니다 . 이는 다음과 같이 정의됩니다:

-씨 주문하다

주문하다 서브셸 환경에서 실행되면 해당 출력이 가능한 완성으로 사용됩니다.

이건 정말 간단한 것 같아요. 그런데 이상하게도 그렇지 않습니다. 만약 내가한다면:

$ complete -C "echo one two three" test.sh

그런 다음 [tab]을 한 번 입력 test.sh하고 클릭하면 행이 채워집니다.

$ test.sh one two three test.sh  test.sh

물러서세요. 무엇? ! 비교하려고,

$ complete -W "one two three" test.sh

내가 기대했던 것과 정확히 일치합니다.하나,, 또는가능한 한 많이 작성하세요(물론 정렬된 순서대로).

어디에서도 좋은 문서를 찾을 수 없어서 시도해 보고 있습니다. 세미콜론이 도움이 될까요? complete -C "echo one two three;" test.sh...아, 알았어, 도움이 됐어일부test.sh, 마지막 이상한 부분을 제거하기 때문입니다. 하지만 여전히 완전한 문자열을 채웁니다 one two three. 위의 설명이 "가능한 완성", 복수형으로 확실히 나와 있기 때문에 이것은 이상합니다. ...그럼, 음, 아, 개행 문자는요? 해 보자 complete -C "echo -e 'one\ntwo\nthree';" test.sh.

그렇군요, 희망은 있습니다. 이것을 입력하면 test.sh [tab]다시 돌아올 것입니다 one three two. 그런데 상황이 잘못되었습니다. o모호함을 해결하기 위해 하나를 추가하므로 , test.sh o[tab],저것반품

o      one    three  two

이것은 수수께끼입니다. 실제로 내가 입력하는 모든 문자열이 목록에 추가됩니다. 이렇게 하면 응답을 test.sh wtf[tab]받게 됩니다 . one three two wtf뭔가 복잡한 일을 해야 할 것 같다고 생각했는데 compgen, 역시 예상대로다 -W. 그리고 사실

$ complete -W '$(echo one two three)' test.sh

echo잘 작동합니다( 변경 가능한 결과를 생성할 수 있는 것보다 더 복잡한 작업을 수행하는 경우 조기 확장/실행을 방지하기 위해 작은따옴표에 유의하세요 ).

내가 여기서 무엇을 놓치고 있는 걸까요?

답변1

이 명령의 역할은 -C완료 요청에 대한 응답으로 삽입할 텍스트를 결정하는 것입니다. 인터페이스가 조금 이상합니다.

  • 인수는 -Cbash 스크립트 조각으로 해석됩니다. Bash는 이 코드 조각에 올바르게 인용된 세 개의 문자열을 추가합니다.

    • 인수가 완료되는 명령입니다.
    • 커서가 위치한 단어의 접두사(커서까지).
    • 커서 앞의 단어입니다.
  • 일부 변수가 환경에 추가됩니다.

    • COMP_LINE실행이 완료된 전체 행을 포함합니다.
    • COMP_POINT여기에는 커서 위치 COMP_LINE(0부터 계산)가 포함됩니다.
    • COMP_TYPE정상 완성은 9번, 모호한 완성에 대한 대안 나열은 33번, 메뉴 완성은 37번, 모호한 완성 간 전환은 63번, 부분 완료 후 나열 완료는 64번이다.
    • COMP_KEY완료를 트리거한 키를 포함합니다(예: 사용자가 누른 경우 tab Tab).
  • 명령의 출력은 현재 단어를 대체하는 텍스트로 해석됩니다. 이는 추가된 접미사가 아닌 대체 접미사입니다. 명령은 지정된 접두사를 기준으로 필터링해야 합니다. 여기에는 여러 줄이 포함될 수 있으며, 이 경우 각 줄은 가능한 대체 줄로 간주됩니다.

이는 제공된 메커니즘과 거의 동일하지만 더 좋습니다.녹음된, 가 있는 함수의 경우 -F. 함수의 인터페이스가 더 깔끔해졌습니다. 현재 명령의 단어 목록을 읽을 수 있습니다.COMP_WORDS변수 및 현재 단어의 시작 위치COMP_CWORD;그들은 결과를 다음과 같이 씁니다.COMPREPLY대량으로.

유용한 인수(특히 완성할 접두사)가 명령 끝에 전달되기 때문에 이는 -C거의 외부 명령에서만 사용할 수 있습니다 . 물론 비슷한 것을 사용할 수도 있지만 sh -c …예쁘지는 않습니다.

complete -C 'sh -c '\'for x in one two three; do case $x in "$1"*) echo "$x";; esac''\'

답변2

complete번거로운 외부 스크립트 및 함수 없이 정의 내에서 완성 기능을 유지하려는 경우 complete -C이 옵션을 사용하는 가장 쉬운 방법은 명령 문자열 내에서 처리기 함수를 정의하는 것입니다. 내장 complete함수는 아래와 같이 명령 문자열을 실행한 직후에 세 개의 문자열을 추가합니다.@Gilles "그러니 악한 행동은 그만하세요"그의 대답에서 그는 이렇게 말했습니다.

  1. 인수가 완료되는 명령입니다.
  2. 커서가 위치한 단어의 접두사(커서까지).
  3. 커서 앞의 단어입니다.

원래 질문의 예제 코드의 경우 가능한 완성을 접두사로 $2포함하려면 위치 인수만 필요합니다. 가는 방법은 다음과 같습니다.grep$2

    complete -C 'makelist() { echo one; echo two; echo three; }; filter() { makelist | grep "^$2" | sort -u; }; filter' test.sh

test.sh t<tab>를 입력하면 complete공백이 포함된 명령 문자열이 마지막 문자열에 "test.sh", "t" 및 "test.sh"가 추가되어 실행됩니다 filter. 이 명령은 다음을 수행합니다.

  • makelist기능 정의
  • filter기능 정의
  • filter추가 문자열을 인수로 사용하여 함수 호출
    • filter통지됩니다makelist
    • makelist가능한 모든 완료 목록을 반환합니다.
    • grep커서 아래 단어의 접두어를 커서까지 일치시켜 완성
    • 특이한 점은 바로 sort이것 이다
    • 다시 돌려줘complete

관련 정보